home *** CD-ROM | disk | FTP | other *** search
/ Inside Macintosh / Inside Macintosh CD-ROM_1995 (CD).toast / Books / Interapplication Comm / Interapplication Comm
Encoding:
Text File  |  1994-08-11  |  13.2 MB  |  40,181 lines  |  [ONLN/HLX2]

Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
  1. INSIDE MACINTOSH
  2.  
  3. Interapplication Communication
  4.  
  5. ISBN 0-201-62200-9
  6. 1 2 3 4 5 6 7 8 9-MU-9796959493
  7. First Printing, June 1993
  8.  
  9.  
  10.     Apple Computer, Inc.
  11. © 1993, Apple Computer, Inc.
  12. All rights reserved. 
  13. No part of this publication may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, mechanical, electronic, photocopying, recording, or otherwise, without prior written permission of Apple Computer, Inc. Printed in the United States of America.
  14. No licenses, express or implied, are granted with respect to any of the technology described in this book. Apple retains all intellectual property rights associated with the technology described in this book. This book is intended to assist application developers to develop applications only for Apple Macintosh computers.
  15. Apple Computer, Inc.
  16. 20525 Mariani Avenue
  17. Cupertino, CA 95014
  18. 408-996-1010
  19. Apple, the Apple logo, APDA, AppleLink, AppleTalk, LaserWriter, Macintosh, MPW, and SANE are trademarks of Apple Computer, Inc., registered in the United States and other countries.
  20. AppleScript, Finder, Moof, New York, QuickDraw, QuickTime, and System 7 are trademarks of Apple Computer, Inc.
  21. Adobe Illustrator, Adobe Photoshop, and PostScript are trademarks of Adobe Systems Incorporated, which may be registered in certain jurisdictions.
  22. America Online is a service mark of Quantum Computer Services, Inc.
  23. CompuServe is a registered trademark of CompuServe, Inc.
  24. FrameMaker is a registered trademark of Frame Technology Corporation.
  25. Helvetica, Palatino, and Times are registered trademarks of Linotype Company.
  26. HyperCard and HyperTalk are registered trademarks of Claris Corporation.
  27. Internet is a trademark of Digital Equipment Corporation.
  28. ITC Zapf Dingbats is a registered trademark of International Typeface Corporation.
  29. Optrotech is a trademark of Orbotech Corporation.
  30. Simultaneously published in the United States and Canada.
  31. LIMITED WARRANTY ON MEDIA AND REPLACEMENT
  32. ALL IMPLIED WARRANTIES ON THIS MANUAL, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE LIMITED IN DURATION TO NINETY (90) DAYS FROM THE DATE OF THE ORIGINAL RETAIL PURCHASE OF THIS PRODUCT.
  33. Even though Apple has reviewed this manual, APPLE MAKES NO WARRANTY OR REPRESENTATION, EITHER EXPRESS OR IMPLIED, WITH RESPECT TO THIS MANUAL, ITS QUALITY, ACCURACY, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. AS A RESULT, THIS MANUAL IS SOLD “AS IS,” AND YOU, THE PURCHASER, ARE ASSUMING THE ENTIRE RISK AS TO ITS QUALITY AND ACCURACY.
  34. IN NO EVENT WILL APPLE BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES RESULTING FROM ANY DEFECT OR INACCURACY IN THIS MANUAL, even if advised of the possibility of such damages.
  35. THE WARRANTY AND REMEDIES SET FORTH ABOVE ARE EXCLUSIVE AND IN LIEU OF ALL OTHERS, ORAL OR WRITTEN, EXPRESS OR IMPLIED. No Apple dealer, agent, or employee is authorized to make any modification, extension, or addition to this warranty.
  36. Some states do not allow the exclusion or limitation of implied warranties or liability for incidental or consequential damages, so the above limitation or exclusion may not apply to you. This warranty gives you specific legal rights, and you may also have other rights which vary from state to state.
  37. Contents
  38. Figures, Tables, and Listingsxv
  39. Preface    About This Bookxxiii
  40.  
  41. Format of a Typical Chapterxxiv
  42. Conventions Used in This Bookxxv
  43. Special Fontsxxv
  44. Types of Notesxxv
  45. Assembly-Language Informationxxvi
  46. The Development Environmentxxvi
  47. Chapter 1    Introduction to Interapplication Communication1-1
  48.  
  49. Overview of Interapplication Communication1-3
  50. Sharing Data Among Applications1-6
  51. Sending and Responding to Apple Events1-9
  52. Standard Apple Events1-10
  53. Handling Apple Events1-12
  54. Supporting AppleScript and Other Scripting Languages1-13
  55. Scriptable Applications1-16
  56. Recordable Applications1-18
  57. Applications That Manipulate and Execute Scripts1-19
  58. Exchanging Message Blocks1-22
  59. Chapter 2    Edition Manager2-1
  60.  
  61. Introduction to Publishers, Subscribers, and Editions2-4
  62. About the Edition Manager2-12
  63. Using the Edition Manager2-12
  64. Receiving Apple Events From the Edition Manager2-13
  65. Creating the Section Record and Alias Record2-15
  66. Saving a Document Containing Sections2-19
  67. Opening and Closing a Document Containing Sections2-22
  68. Reading and Writing a Section2-24
  69. Formats in an Edition2-24
  70. Opening an Edition2-26
  71. Format Marks2-27
  72. Reading and Writing Edition Data2-27
  73. Closing an Edition2-28
  74. Creating a Publisher2-29
  75. Creating the Edition Container2-32
  76. Opening an Edition Container to Write Data2-35
  77. Creating a Subscriber2-37
  78. Opening an Edition Container to Read Data2-41
  79. Choosing Which Edition Format to Read2-41
  80. Using Publisher and Subscriber Options2-43
  81. Publishing a New Edition While Saving or Manually2-47
  82. Subscribing to an Edition Automatically or Manually2-48
  83. Canceling Sections Within Documents2-48
  84. Locating a Publisher Through a Subscriber2-49
  85. Renaming a Document Containing Sections2-50
  86. Displaying Publisher and Subscriber Borders2-50
  87. Text Borders2-54
  88. Spreadsheet Borders2-55
  89. Object-Oriented Graphics Borders2-56
  90. Bitmapped Graphics Borders2-57
  91. Duplicating Publishers and Subscribers2-58
  92. Modifying a Subscriber2-59
  93. Relocating an Edition2-60
  94. Customizing Dialog Boxes2-60
  95. Subscribing to Non-Edition Files2-62
  96. Getting the Current Edition Opener2-63
  97. Setting an Edition Opener2-63
  98. Calling an Edition Opener2-64
  99. Opening and Closing Editions2-68
  100. Listing Files That Can Be Subscribed To2-68
  101. Reading From and Writing to Files2-68
  102. Calling a Format I/O Function2-68
  103. Edition Manager Reference2-71
  104. Data Structures2-71
  105. The Edition Container Record2-71
  106. The Section Record2-72
  107. Edition Manager Routines2-73
  108. Initializing the Edition Manager2-74
  109. Creating and Registering a Section2-74
  110. Creating and Deleting an Edition Container2-79
  111. Setting and Getting a Format Mark2-81
  112. Reading in Edition Data2-83
  113. Writing out Edition Data2-86
  114. Closing an Edition After Reading or Writing2-88
  115. Displaying Dialog Boxes2-90
  116. Locating a Publisher and Edition From a Subscriber2-98
  117. Edition Container Formats2-101
  118. Reading and Writing Non-Edition Files2-102
  119. Application-Defined Routines2-105
  120. Summary of the Edition Manager2-106
  121. Pascal Summary2-106
  122. Constants2-106
  123. Data Types2-108
  124. Edition Manager Routines2-111
  125. Application-Defined Routines2-113
  126. C Summary2-114
  127. Constants2-114
  128. Data Types2-116
  129. Edition Manager Routines2-119
  130. Application-Defined Routines2-122
  131. Result Codes2-122
  132. Chapter 3    Introduction to Apple Events3-1
  133.  
  134. About Apple Events3-3
  135. Apple Events and Apple Event Objects3-6
  136. Apple Event Attributes and Parameters3-7
  137. Apple Event Attributes3-8
  138. Apple Event Parameters3-9
  139. Interpreting Apple Event Attributes and Parameters3-10
  140. Data Structures Within Apple Events3-12
  141. Descriptor Records3-12
  142. Keyword-Specified Descriptor Records3-15
  143. Descriptor Lists3-16
  144. Responding to Apple Events3-20
  145. Accepting and Processing Apple Events3-20
  146. About Apple Event Handlers3-23
  147. Extracting and Checking Data3-23
  148. Interacting With the User3-25
  149. Performing the Requested Action and Returning a Result3-25
  150. Creating and Sending Apple Events3-28
  151. Creating an Apple Event Record3-29
  152. Adding Apple Event Attributes and Parameters3-29
  153. Sending an Apple Event and Handling the Reply3-30
  154. Working With Object Specifier Records3-32
  155. Data Structures Within an Object Specifier Record3-34
  156. The Classification of Apple Event Objects3-39
  157. Object Classes3-39
  158. Properties and Elements3-42
  159. Finding Apple Event Objects3-46
  160. About the Apple Event Manager3-48
  161. Supporting Apple Events as a Server Application3-48
  162. Supporting Apple Events as a Client Application3-49
  163. Supporting Apple Event Objects3-49
  164. Supporting Apple Event Recording3-50
  165. Chapter 4    Responding to Apple Events4-1
  166.  
  167. Handling Apple Events4-4
  168. Accepting an Apple Event4-5
  169. Installing Entries in the Apple Event Dispatch Tables4-7
  170. Installing Entries for the Required Apple Events4-8
  171. Installing Entries for Apple Events Sent by the Edition Manager4-9
  172. How Apple Event Dispatching Works4-9
  173. Handling the Required Apple Events4-11
  174. Required Apple Events4-11
  175. Handling the Open Application Event4-14
  176. Handling the Open Documents Event4-15
  177. Handling the Print Documents Event4-17
  178. Handling the Quit Application Event4-19
  179. Handling Apple Events Sent by the Edition Manager4-20
  180. The Section Read, Section Write, and Section Scroll Events4-21
  181. Handling the Create Publisher Event4-22
  182. Getting Data Out of an Apple Event4-25
  183. Getting Data Out of an Apple Event Parameter4-26
  184. Getting Data Out of an Attribute4-28
  185. Getting Data Out of a Descriptor List4-31
  186. Writing Apple Event Handlers4-33
  187. Replying to an Apple Event4-36
  188. Disposing of Apple Event Data Structures4-39
  189. Writing and Installing Coercion Handlers4-41
  190. Interacting With the User4-45
  191. Setting the Client Application’s User Interaction Preferences4-46
  192. Setting the Server Application’s User Interaction Preferences4-48
  193. Requesting User Interaction4-49
  194. Reference to Responding to Apple Events4-56
  195. Data Structures Used by the Apple Event Manager4-56
  196. Descriptor Records and Related Data Structures4-56
  197. Apple Event Array Data Types4-60
  198. Routines for Responding to Apple Events4-61
  199. Creating and Managing the Apple Event Dispatch Tables4-61
  200. Dispatching Apple Events4-66
  201. Getting Data or Descriptor Records Out of Apple Event Parameters and Attributes4-68
  202. Counting the Items in Descriptor Lists4-74
  203. Getting Items From Descriptor Lists4-74
  204. Getting Data and Keyword-Specified Descriptor Records Out of AE Records4-78
  205. Requesting User Interaction4-81
  206. Requesting More Time to Respond to Apple Events4-84
  207. Suspending and Resuming Apple Event Handling4-85
  208. Getting the Sizes and Descriptor Types of Descriptor Records4-89
  209. Deleting Descriptor Records4-92
  210. Deallocating Memory for Descriptor Records4-93
  211. Coercing Descriptor Types4-94
  212. Creating and Managing the Coercion Handler Dispatch Tables4-96
  213. Creating and Managing the Special Handler Dispatch Tables4-99
  214. Getting Information About the Apple Event Manager4-103
  215. Application-Defined Routines4-104
  216. Summary of Responding to Apple Events4-108
  217. Pascal Summary4-108
  218. Constants4-108
  219. Data Types4-112
  220. Routines for Responding to Apple Events4-114
  221. Application-Defined Routines4-118
  222. C Summary4-118
  223. Constants4-118
  224. Data Types4-123
  225. Routines for Responding to Apple Events4-124
  226. Application-Defined Routines4-128
  227. Assembly-Language Summary4-128
  228. Trap Macros4-128
  229. Result Codes4-130
  230. Chapter 5    Creating and Sending Apple Events5-1
  231.  
  232. Creating an Apple Event5-3
  233. Adding Parameters to an Apple Event5-5
  234. Specifying Optional Parameters for an Apple Event5-7
  235. Specifying a Target Address5-10
  236. Creating an Address Descriptor Record5-11
  237. Addressing an Apple Event for Direct Dispatching5-13
  238. Sending an Apple Event5-13
  239. Dealing With Timeouts5-20
  240. Writing an Idle Function5-21
  241. Writing a Reply Filter Function5-24
  242. Reference to Creating and Sending Apple Events5-24
  243. Routines for Creating and Sending Apple Events5-25
  244. Creating Apple Events5-25
  245. Creating and Duplicating Descriptor Records5-26
  246. Creating Descriptor Lists and AE Records5-28
  247. Adding Items to Descriptor Lists5-29
  248. Adding Data and Descriptor Records to AE Records5-32
  249. Adding Parameters and Attributes to Apple Events5-33
  250. Sending Apple Events5-37
  251. Application-Defined Routines5-41
  252. Summary of Creating and Sending Apple Events5-44
  253. Pascal Summary5-44
  254. Constants5-44
  255. Data Types5-48
  256. Routines for Creating and Sending Apple Events5-50
  257. Application-Defined Routines5-51
  258. C Summary5-51
  259. Constants5-51
  260. Data Types5-56
  261. Routines for Creating and Sending Apple Events5-57
  262. Application-Defined Routines5-59
  263. Assembly-Language Summary5-59
  264. Trap Macros5-59
  265. Result Codes5-60
  266. Chapter 6    Resolving and Creating Object Specifier Records6-1
  267.  
  268. Resolving Object Specifier Records6-4
  269. Descriptor Records Used in Object Specifier Records6-8
  270. Object Class6-9
  271. Container6-9
  272. Key Form6-11
  273. Key Data6-12
  274. Key Data for a Property ID6-13
  275. Key Data for an Object’s Name6-14
  276. Key Data for a Unique ID6-14
  277. Key Data for Absolute Position6-14
  278. Key Data for Relative Position6-15
  279. Key Data for a Test6-15
  280. Key Data for a Range6-20
  281. Installing Entries in the Object Accessor Dispatch Tables6-21
  282. Installing Object Accessor Functions That Find Apple Event Objects6-23
  283. Installing Object Accessor Functions That Find Properties6-27
  284. Writing Object Accessor Functions6-28
  285. Writing Object Accessor Functions That Find Apple Event Objects6-29
  286. Writing Object Accessor Functions That Find Properties6-37
  287. Defining Tokens6-39
  288. Handling Whose Tests6-41
  289. Writing Object Callback Functions6-45
  290. Writing an Object-Counting Function6-48
  291. Writing an Object-Comparison Function6-50
  292. Writing Marking Callback Functions6-53
  293. Creating Object Specifier Records6-55
  294. Creating a Simple Object Specifier Record6-57
  295. Specifying the Container Hierarchy6-61
  296. Specifying a Property6-63
  297. Specifying a Relative Position6-64
  298. Creating a Complex Object Specifier Record6-64
  299. Specifying a Test6-64
  300. Specifying a Range6-72
  301. Reference to Resolving and Creating Object Specifier Records6-75
  302. Data Structures Used in Object Specifier Records6-75
  303. Routines for Resolving and Creating Object Specifier Records6-77
  304. Initializing the Object Support Library6-77
  305. Setting Object Accessor Functions and Object Callback Functions6-77
  306. Getting, Calling, and Removing Object Accessor Functions6-81
  307. Resolving Object Specifier Records6-85
  308. Deallocating Memory for Tokens6-87
  309. Creating Object Specifier Records6-88
  310. Application-Defined Routines6-94
  311. Object Accessor Functions6-94
  312. Object Callback Functions6-96
  313. Summary of Resolving and Creating Object Specifier Records6-104
  314. Pascal Summary6-104
  315. Constants6-104
  316. Data Types6-106
  317. Routines for Resolving and Creating Object Specifier Records6-106
  318. Application-Defined Routines6-108
  319. C Summary6-109
  320. Constants6-109
  321. Data Types6-111
  322. Routines for Resolving and Creating Object Specifier Records6-112
  323. Application-Defined Routines6-114
  324. Assembly-Language Summary6-115
  325. Trap Macros6-115
  326. Result Codes6-115
  327. Chapter 7    Introduction to Scripting7-1
  328.  
  329. About Scripts and Scripting Components7-4
  330. Script Editors and Script Files7-6
  331. Scripting Components and Scriptable Applications7-8
  332. Scripting Components and Applications That Execute Scripts7-11
  333. Making Your Application Scriptable7-14
  334. About Apple Event Terminology Resources7-15
  335. How AppleScript Uses Terminology Information7-17
  336. Dynamic Loading of Terminology Information7-20
  337. Making Your Application Recordable7-20
  338. Manipulating and Executing Scripts7-22
  339. Compiling, Saving, Modifying, and Executing Scripts7-24
  340. Using a Script Context to Handle an Apple Event7-25
  341. Chapter 8    Apple Event Terminology Resources8-1
  342.  
  343. Defining Terminology for Use by the AppleScript Component8-3
  344. Structure of Apple Event Terminology Resources8-8
  345. Creating an Apple Event Terminology Extension Resource8-13
  346. Supporting Standard Suites Without Extensions8-14
  347. Extending the Standard Suites8-16
  348. Supporting Subsets of Suites8-23
  349. Supporting New Suites8-23
  350. Handling the Get AETE Event8-23
  351. Reference to Apple Event Terminology Resources8-26
  352. Header Data for an Apple Event Terminology Resource8-27
  353. Suite Data for an Apple Event Terminology Resource8-27
  354. Event Data8-29
  355. Object Class Data8-36
  356. Comparison Operator Data8-42
  357. Enumeration and Enumerator Data8-43
  358. The Scripting Size Resource8-45
  359. Chapter 9    Recording Apple Events9-1
  360.  
  361. About Recordable Applications9-3
  362. Factoring Your Application for Recording9-6
  363. Factoring the Quit Command and the New Command9-6
  364. Sending Apple Events Without Executing Them9-12
  365. What to Record9-14
  366. Recording User Actions9-15
  367. Recording the Selection of Text Objects9-18
  368. Recording Insertion Points9-23
  369. Recording Typing9-27
  370. Recording the Selection of Nontext Objects9-30
  371. Identifying Objects9-32
  372. Moving the Selection During Recording9-34
  373. Recording Interactions With Dialog Boxes9-35
  374. How Apple Event Recording Works9-35
  375. Chapter 10    Scripting Components10-1
  376.  
  377. Connecting to a Scripting Component10-3
  378. Using Scripting Component Routines10-7
  379. Compiling and Executing Source Data10-7
  380. Saving Script Data10-12
  381. Storage Formats for Script Data10-12
  382. Resource and File Types for Script Data10-13
  383. Loading and Executing Script Data10-14
  384. Modifying and Recompiling a Compiled Script10-17
  385. Using a Script Context to Handle an Apple Event10-19
  386. Supplying a Resume Dispatch Function10-21
  387. Supplying an Alternative Active Function10-23
  388. Supplying Alternative Create and Send Functions10-24
  389. Alternative Create Functions10-24
  390. Alternative Send Functions10-25
  391. Recording Scripts10-26
  392. Writing a Scripting Component10-27
  393. Scripting Components Reference10-28
  394. Data Structures10-29
  395. Required Scripting Component Routines10-30
  396. Saving and Loading Script Data10-30
  397. Executing and Disposing of Scripts10-33
  398. Setting and Getting Script Information10-41
  399. Manipulating the Active Function10-45
  400. Optional Scripting Component Routines10-46
  401. Compiling Scripts10-47
  402. Getting Source Data10-51
  403. Coercing Script Values10-52
  404. Manipulating the Create and Send Functions10-55
  405. Recording Scripts10-59
  406. Executing Scripts in One Step10-61
  407. Manipulating Dialects10-67
  408. Using Script Contexts to Handle Apple Events10-71
  409. AppleScript Component Routines10-80
  410. Initializing AppleScript10-80
  411. Getting and Setting Styles for Source Data10-82
  412. Generic Scripting Component Routines10-84
  413. Getting and Setting the Default Scripting Component10-86
  414. Using Component-Specific Routines10-87
  415. Routines Used by Scripting Components10-92
  416. Manipulating Trailers for Generic Storage Descriptor Records10-92
  417. Application-Defined Routines10-94
  418. Summary of Scripting Components10-99
  419. Pascal Summary10-99
  420. Constants10-99
  421. Data Types10-105
  422. Required Scripting Component Routines10-106
  423. Optional Scripting Component Routines10-107
  424. AppleScript Component Routines10-110
  425. Generic Scripting Component Routines10-110
  426. Routines Used by Scripting Components10-111
  427. Application-Defined Routines10-111
  428. C Summary10-112
  429. Constants10-112
  430. Data Types10-118
  431. Required Scripting Component Routines10-119
  432. Optional Scripting Component Routines10-120
  433. AppleScript Component Routines10-123
  434. Generic Scripting Component Routines10-123
  435. Routines Used by Scripting Components10-124
  436. Application-Defined Routines10-124
  437. Result Codes10-125
  438. Chapter 11    Program-to-Program Communications Toolbox11-1
  439.  
  440. About the PPC Toolbox11-4
  441. Ports, Sessions, and Message Blocks11-4
  442. Setting Up Authenticated Sessions11-6
  443. Using the PPC Toolbox11-10
  444. PPC Toolbox Calling Conventions11-14
  445. Specifying Port Names and Location Names11-17
  446. Opening a Port11-20
  447. Browsing for Ports Using the Program Linking Dialog Box11-22
  448. Obtaining a List of Available Ports11-27
  449. Preparing for a Session11-29
  450. Initiating a PPC Session11-29
  451. Receiving Session Requests11-35
  452. Accepting or Rejecting Session Requests11-37
  453. Exchanging Data During a PPC Session11-39
  454. Reading Data From an Application11-40
  455. Sending Data to an Application11-42
  456. Ending a Session and Closing a Port11-43
  457. Invalidating Users11-44
  458. PPC Toolbox Reference11-46
  459. Data Structures11-46
  460. The PPC Toolbox Parameter Block11-46
  461. The PPC Port Record11-48
  462. The Location Name Record11-49
  463. The Port Information Record11-50
  464. PPC Toolbox Routines11-50
  465. Initializing the PPC Toolbox11-51
  466. Using the Program Linking Dialog Box11-51
  467. Obtaining a List of Ports11-54
  468. Opening and Closing a Port11-56
  469. Starting and Ending a Session11-59
  470. Receiving, Accepting, and Rejecting a Session11-66
  471. Reading and Writing Data11-71
  472. Locating a Default User and Invalidating a User11-75
  473. Application-Defined Routines11-77
  474. Completion Routines for PPC Toolbox Routines11-77
  475. Port Filter Functions11-78
  476. Summary of the PPC Toolbox11-80
  477. Pascal Summary11-80
  478. Constants11-80
  479. Data Types11-81
  480. PPC Toolbox Routines11-87
  481. Application-Defined Routines11-88
  482. C Summary11-89
  483. Constants11-89
  484. Data Types11-90
  485. PPC Toolbox Routines11-95
  486. Application-Defined Routines11-96
  487. Assembly-Language Summary11-96
  488. Trap Macros11-96
  489. Result Codes11-97
  490. Chapter 12    Data Access Manager12-1
  491.  
  492. About the Data Access Manager12-5
  493. The High-Level Interface12-7
  494. Sending a Query Through the High-Level Interface12-8
  495. Retrieving Data Through the High-Level Interface12-9
  496. The Low-Level Interface12-9
  497. Sending a Query Through the Low-Level Interface12-10
  498. Retrieving Data Through the Low-Level Interface12-11
  499. Comparison of the High-Level and Low-Level Interfaces12-11
  500. Using the Data Access Manager12-12
  501. Executing Routines Asynchronously12-12
  502. General Guidelines for the User Interface12-13
  503. Keep the User in Control12-13
  504. Provide Feedback to the User12-13
  505. Using the High-Level Interface12-14
  506. Writing a Status Routine for High-Level Functions12-22
  507. Using the Low-Level Interface12-28
  508. Getting Information About Sessions in Progress12-35
  509. Processing Query Results12-36
  510. Getting Query Results12-36
  511. Converting Query Results to Text12-42
  512. Creating a Query Document12-46
  513. User Interface Guidelines for Query Documents12-46
  514. Contents of a Query Document12-48
  515. Query Records and Query Resources12-51
  516. Writing a Query Definition Function12-51
  517. Data Access Manager Reference12-54
  518. Data Structures12-54
  519. The Asynchronous Parameter Block12-55
  520. The Query Record12-56
  521. The Results Record12-58
  522. Data Access Manager Routines12-59
  523. Initializing the Data Access Manager12-60
  524. High-Level Interface: Handling Query Documents12-61
  525. High-Level Interface: Handling Query Results12-65
  526. Low-Level Interface: Controlling the Session12-68
  527. Low-Level Interface: Sending and Executing Queries12-76
  528. Low-Level Interface: Retrieving Results12-82
  529. Installing and Removing Result Handlers12-86
  530. Application-Defined Routines12-89
  531. Resources12-90
  532. The Query Resource12-90
  533. The Query String Resource12-91
  534. The Query Definition Function Resource12-92
  535. Summary of the Data Access Manager12-93
  536. Pascal Summary12-93
  537. Constants12-93
  538. Data Types12-94
  539. Data Access Manager Routines12-96
  540. Application-Defined Routines12-98
  541. C Summary12-98
  542. Constants12-98
  543. Data Types12-100
  544. Data Access Manager Routines12-101
  545. Application-Defined Routines12-103
  546. Assembly-Language Summary12-103
  547. Trap Macros12-103
  548. Result Codes12-104
  549. GlossaryGL-1
  550.  
  551. IndexIN-1
  552. Figures, Tables, and Listings
  553. Preface    About This Bookxxiii
  554.  
  555. Chapter 1    Introduction to Interapplication Communication1-1
  556.  
  557. Figure 1-1    Principal methods of communication between applications1-5
  558. Figure 1-2    Sharing data with the aid of the Edition Manager1-7
  559. Figure 1-3    A publisher, an edition, and a subscriber1-8
  560. Figure 1-4    Sharing dynamic data with other applications1-8
  561. Figure 1-5    Sending and responding to Apple events with the aid of the Apple Event Manager1-10
  562. Figure 1-6    A Set Data event1-12
  563. Figure 1-7    How a scripting component executes a script1-14
  564. Figure 1-8    A Set Data event sent during script execution1-17
  565. Figure 1-9    Recording user actions in a factored application1-19
  566. Figure 1-10    Controlling an application’s own behavior by executing a script1-20
  567. Figure 1-11    Posting an invoice and updating a database by executing a script1-21
  568. Chapter 2    Edition Manager2-1
  569.  
  570. Figure 2-1    The default edition icon2-4
  571. Figure 2-2    A publisher, an edition, and a subscriber2-5
  572. Figure 2-3    The publisher dialog box2-5
  573. Figure 2-4    The subscriber dialog box2-7
  574. Figure 2-5    A document and its corresponding editions2-8
  575. Figure 2-6    Publisher and subscriber borders2-9
  576. Figure 2-7    Edition Manager commands in the Edit menu2-10
  577. Figure 2-8    Edition Manager commands under the Publishing menu command2-11
  578. Figure 2-9    A document with a publisher and subscriber and its resource fork2-16
  579. Figure 2-10    The new publisher alert box2-19
  580. Figure 2-11    A sample publisher dialog box2-29
  581. Figure 2-12    A sample subscriber dialog box2-37
  582. Figure 2-13    The publisher options dialog box with update mode set to On Save2-43
  583. Figure 2-14    The publisher options dialog box with update mode set to Manually2-44
  584. Figure 2-15    The subscriber options dialog box with update mode set to Automatically2-44
  585. Figure 2-16    The subscriber options dialog box with update mode set to Manually2-45
  586. Figure 2-17    Edit menu with Show/Hide Borders menu command2-51
  587. Figure 2-18    Publisher borders2-52
  588. Figure 2-19    Subscriber borders2-53
  589. Figure 2-20    A publisher with contents removed2-54
  590. Figure 2-21    A publisher border within a spreadsheet document2-55
  591. Figure 2-22    A publisher border with resize handles2-56
  592. Figure 2-23    A publisher and subscriber with clipped graphics2-57
  593. Figure 2-24    Creating multiple publishers alert box2-58
  594. Figure 2-25    Saving multiple publishers alert box2-58
  595. Figure 2-26    Subscribing directly to a 'PICT' file2-62
  596. Listing 2-1    Accepting Section Read events and verifying if a section is registered2-14
  597. Listing 2-2    Saving a document containing sections2-21
  598. Listing 2-3    Opening a document containing sections2-23
  599. Listing 2-4    Creating a publisher2-33
  600. Listing 2-5    Writing data to an edition2-36
  601. Listing 2-6    Creating a subscriber2-40
  602. Listing 2-7    Reading in edition data2-42
  603. Listing 2-8    Responding to action codes2-46
  604. Listing 2-9    Using your own edition opener function2-67
  605. Chapter 3    Introduction to Apple Events3-1
  606.  
  607. Figure 3-1    An Open Documents event3-4
  608. Figure 3-2    A Get Data event3-7
  609. Figure 3-3    Major attributes and direct parameter of an Open Documents event3-10
  610. Figure 3-4    Major attributes and direct parameter of a Get Data event3-11
  611. Figure 3-5    A descriptor record whose data handle refers to an unterminated string3-13
  612. Figure 3-6    A descriptor record whose data handle refers to event class data3-14
  613. Figure 3-7    A keyword-specified descriptor record for the event class attribute of an Open Documents event3-16
  614. Figure 3-8    A descriptor list for a list of aliases3-17
  615. Figure 3-9    Data structures within an Open Documents event3-19
  616. Figure 3-10    Accepting and processing an Open Documents event3-21
  617. Figure 3-11    The Apple Event Manager calling the handler for an Open Documents event3-22
  618. Figure 3-12    Responding to an Open Documents event3-27
  619. Figure 3-13    Data structures within a simple object specifier record3-37
  620. Figure 3-14    An object specifier record in a Get Data event3-38
  621. Figure 3-15    Superclasses and subclasses3-40
  622. Figure 3-16    The object class inheritance hierarchy for the object class cWindow3-44
  623. Figure 3-17    An Apple event object of class cWord contained in an Apple event object of class cParagraph3-46
  624. Chapter 4    Responding to Apple Events4-1
  625.  
  626. Figure 4-1    A document with a button that triggers a Get Data event4-51
  627. Figure 4-2    A server application displaying a dialog box that requests information from the user4-52
  628. Figure 4-3    Handling user interaction4-53
  629. Figure 4-4    Handling user interaction with the kAEWaitReply flag set4-54
  630. Figure 4-5    Handling user interaction with the kAEQueueReply flag set4-55
  631. Table 4-1    Coercion handling provided by the Apple Event Manager4-43
  632. Table 4-2    Descriptor types used by the Apple Event Manager (excluding those used with object specifier records)4-57
  633. Listing 4-1    A DoEvent procedure4-5
  634. Listing 4-2    A DoHighLevelEvent procedure for handling Apple events and other high-level events4-6
  635. Listing 4-3    Adding entries for the required Apple events to an application’s Apple event dispatch table4-8
  636. Listing 4-4    Adding entries for Apple events sent by the Edition Manager to an application’s Apple event dispatch table4-9
  637. Listing 4-5    A handler for the Open Application event4-15
  638. Listing 4-6    A handler for the Open Documents event4-15
  639. Listing 4-7    A handler for the Print Documents event4-18
  640. Listing 4-8    A handler for the Quit Application event4-19
  641. Listing 4-9    A handler for the Create Publisher event4-23
  642. Listing 4-10    Extracting items from a descriptor list4-33
  643. Listing 4-11    A function that checks for a keyMissedKeywordAttr attribute4-35
  644. Listing 4-12    Adding the keyErrorString parameter to the reply Apple event4-38
  645. Listing 4-13    Adding parameters to the reply Apple event4-39
  646. Listing 4-14    Using the AEInteractWithUser function4-50
  647. Chapter 5    Creating and Sending Apple Events5-1
  648.  
  649. Listing 5-1    Creating the optional keyword for the Create Publisher event5-9
  650. Listing 5-2    Creating a target address5-11
  651. Listing 5-3    Specifying a target address in an Apple event by using the PPCBrowser function5-12
  652. Listing 5-4    Sending an Apple event5-17
  653. Listing 5-5    An idle function5-23
  654. Chapter 6    Resolving and Creating Object Specifier Records6-1
  655.  
  656. Figure 6-1    Resolving an object specifier record for a table in a document6-6
  657. Figure 6-2    Nested object specifier records that specify a container hierarchy6-10
  658. Figure 6-3    The container hierarchy for the first row in a table that meets a test6-18
  659. Figure 6-4    A logical descriptor record that specifies a test6-19
  660. Figure 6-5    Descriptor record for an application-defined token that identifies a document6-39
  661. Figure 6-6    Descriptor record for an application-defined token that identifies the pbounds property of a window6-40
  662. Figure 6-7    A container hierarchy created by the Apple Event Manager using a whose descriptor record6-43
  663. Table 6-1    Standard descriptor types used with keyAEKeyData6-12
  664. Table 6-2    Keyword-specified descriptor records for typeCompDescriptor6-16
  665. Table 6-3    Keyword-specified descriptor records for typeLogicalDescriptor6-17
  666. Table 6-4    Keyword-specified descriptor records in a descriptor record of type typeRangeDescriptor6-20
  667. Table 6-5    Keyword-specified descriptor records for typeWhoseDescriptor6-42
  668. Table 6-6    Keyword-specified descriptor records for typeWhoseRange6-44
  669. Table 6-7    Nested object specifier records that describe a container hierarchy6-56
  670. Table 6-8    Object specifier record for the first row that meets a test in the table named “MyAddresses”6-65
  671. Table 6-9    Logical descriptor record that specifies a test6-66
  672. Table 6-10    A range descriptor record6-73
  673. Table 6-11    Keyword-specified descriptor records for typeObjectSpecifier6-76
  674. Listing 6-1    Installing object accessor functions that find elements of different classes for container tokens of the same type6-23
  675. Listing 6-2    Installing one object accessor function that finds elements of different classes for container tokens of one type6-25
  676. Listing 6-3    Installing object accessor functions that find elements of the same class for container tokens of different types6-25
  677. Listing 6-4    Installing object accessor functions that locate elements of different classes in the default container6-26
  678. Listing 6-5    An object accessor function that locates Apple event objects of object class cDocument6-30
  679. Listing 6-6    An object accessor function that locates Apple event objects of object class cParagraph6-32
  680. Listing 6-7    An object accessor function that locates Apple event objects of object class cWord6-34
  681. Listing 6-8    An object accessor function that locates Apple event objects of object class cWindow6-35
  682. Listing 6-9    An object accessor function that identifies any property of a window6-38
  683. Listing 6-10    An object-counting function6-49
  684. Listing 6-11    Object-comparison function that compares two Apple event objects6-52
  685. Listing 6-12    Creating an object specifier record using CreateObjSpecifier6-58
  686. Listing 6-13    Using CreateObjSpecifier in an application-defined function6-59
  687. Listing 6-14    Specifying a document container6-61
  688. Listing 6-15    Specifying a table container6-62
  689. Listing 6-16    Creating an object specifier record with the key form formName6-67
  690. Listing 6-17    Creating a comparison descriptor record6-68
  691. Listing 6-18    Creating a logical descriptor record6-70
  692. Listing 6-19    Creating a complex object specifier record6-70
  693. Listing 6-20    Creating a range descriptor record6-74
  694. Chapter 7    Introduction to Scripting7-1
  695.  
  696. Figure 7-1    A script window in the Script Editor application7-6
  697. Figure 7-2    Script file icons in the Finder and corresponding user actions7-7
  698. Figure 7-3    How the AppleScript component executes a script7-9
  699. Figure 7-4    How an application uses the AppleScript component to execute a script7-13
  700. Figure 7-5    Role of the 'aete' and 'aeut' resources when the AppleScript component compiles and executes a script7-18
  701. Figure 7-6    Role of the 'aete' and 'aeut' resources when the AppleScript component records and decompiles a script7-19
  702. Figure 7-7    Using a handler in a script context to handle an Apple event7-26
  703. Chapter 8    Apple Event Terminology Resources8-1
  704.  
  705. Figure 8-1    Structure of an 'aeut' or 'aete' resource8-26
  706. Figure 8-2    Structure of the header data in an 'aeut' or 'aete' resource8-27
  707. Figure 8-3    Structure of suite data in an 'aeut' or 'aete' resource8-28
  708. Figure 8-4    Structure of event data in an 'aeut' or 'aete' resource8-30
  709. Figure 8-5    Structure of additional parameter data in an 'aeut' or 'aete' resource8-34
  710. Figure 8-6    Structure of object class data in an 'aeut' or 'aete' resource8-36
  711. Figure 8-7    Structure of property data in an 'aeut' or 'aete' resource8-38
  712. Figure 8-8    Structure of element class data in an 'aeut' or 'aete' resource8-41
  713. Figure 8-9    Structure of comparison operator data in an 'aeut' or 'aete' resource8-42
  714. Figure 8-10    Structure of enumeration data in an 'aeut' or 'aete' resource8-43
  715. Figure 8-11    Structure of enumerator data in an 'aeut' or 'aete' resource8-44
  716. Table 8-1    Syntax for AppleScript arguments that correspond to direct parameters8-5
  717. Table 8-2    Syntax for AppleScript arguments that correspond to insertion location descriptor records8-6
  718. Table 8-3    Structure of the 'aeut' and 'aete' resources8-8
  719. Listing 8-1    Resource type declaration for the 'aeut' resource8-9
  720. Listing 8-2    Rez input for an 'aete' resource for an application that supports the Required and Core suites in their entirety8-15
  721. Listing 8-3    Rez input for an 'aete' resource that extends the definitions of the Required, Core, and Text suites8-17
  722. Listing 8-4    A handler for the Get AETE event8-25
  723. Listing 8-5    Resource type declaration for the 'scsz' resource8-45
  724. Chapter 9    Recording Apple Events9-1
  725.  
  726. Listing 9-1    A function used by a factored application to send itself a Quit Application event9-7
  727. Listing 9-2    A routine used by a factored application to handle a Quit Application event9-8
  728. Listing 9-3    A routine used by a factored application to send itself a Create Element event9-10
  729. Listing 9-4    The Create Element event handler for a factored application9-11
  730. Listing 9-5    A routine used by a factored application to handle window movement9-13
  731. Chapter 10    Scripting Components10-1
  732.  
  733. Figure 10-1    A generic storage descriptor record10-12
  734. Figure 10-2    A component-specific storage descriptor record10-13
  735. Listing 10-1    Locating a scripting component that supports specific optional routines10-6
  736. Listing 10-2    A routine that compiles and executes source data10-9
  737. Listing 10-3    A procedure that uses OSAScriptError to get information about an execution error10-11
  738. Listing 10-4    A routine that loads and executes script data previously saved using a generic storage descriptor record10-16
  739. Listing 10-5    A routine that displays a compiled script for editing and recompiles it10-18
  740. Listing 10-6    A function that loads and modifies script data, then saves it using a generic storage descriptor record10-19
  741. Listing 10-7    A general Apple event handler that uses the OSADoEvent function10-21
  742. Chapter 11    Program-to-Program Communications Toolbox11-1
  743.  
  744. Figure 11-1    A PPC Toolbox session between two applications11-5
  745. Figure 11-2    The icon for the Sharing Setup control panel11-6
  746. Figure 11-3    The Sharing Setup control panel11-6
  747. Figure 11-4    The session termination alert box11-7
  748. Figure 11-5    The users and groups dialog box11-8
  749. Figure 11-6    The user termination alert box11-8
  750. Figure 11-7    The guest dialog box11-9
  751. Figure 11-8    The PPC Toolbox authentication process11-10
  752. Figure 11-9    Database and spreadsheet applications using the PPC Toolbox11-13
  753. Figure 11-10    Two Macintosh applications and their corresponding ports11-18
  754. Figure 11-11    The PPC Toolbox and a dictionary service application11-20
  755. Figure 11-12    The program linking dialog box11-22
  756. Figure 11-13    The program linking dialog box without a zone list11-23
  757. Figure 11-14    The user identity dialog box11-30
  758. Figure 11-15    The incorrect password dialog box11-31
  759. Figure 11-16    The invalid user name dialog box11-31
  760. Figure 11-17    Transmitting message blocks11-40
  761. Figure 11-18    The PPC Toolbox parameter blocks11-47
  762. Listing 11-1    Initializing the PPC Toolbox using the PPCInit function11-12
  763. Listing 11-2    Opening a PPC port11-21
  764. Listing 11-3    Using a port filter function11-24
  765. Listing 11-4    Browsing through dictionary service ports11-26
  766. Listing 11-5    Using the IPCListPorts function to obtain a list of ports11-28
  767. Listing 11-6    Using the StartSecureSession function to establish a session11-32
  768. Listing 11-7    Initiating a session using the PPCStart function11-34
  769. Listing 11-8    Using the PPCInform function to enable a port to receive sessions11-36
  770. Listing 11-9    Completion routine for a PPCInform function11-37
  771. Listing 11-10    Accepting a session request using the PPCAccept function11-38
  772. Listing 11-11    Completion routine for a PPCAccept function11-38
  773. Listing 11-12    Rejecting a session request using the PPCReject function11-39
  774. Listing 11-13    Completion routine for a PPCReject function11-39
  775. Listing 11-14    Using the PPCRead function to read data during a session11-41
  776. Listing 11-15    Polling the ioResult field to determine if a PPCRead function has completed11-41
  777. Listing 11-16    Using the PPCWrite function to write data during a session11-42
  778. Listing 11-17    Polling the ioResult field to determine if a PPCWrite function has completed11-43
  779. Listing 11-18    Ending a PPC session using the PPCEnd function11-43
  780. Listing 11-19    Closing a PPC port using the PPCClose function11-44
  781. Listing 11-20    Using the DeleteUserIdentity function to invalidate a user identity11-45
  782. Chapter 12    Data Access Manager12-1
  783.  
  784. Figure 12-1    A connection with a database12-6
  785. Figure 12-2    Using high-level Data Access Manager routines12-8
  786. Figure 12-3    Using low-level Data Access Manager routines12-10
  787. Figure 12-4    A flowchart of a session using the high-level interface12-15
  788. Figure 12-5    A flowchart of a session using the low-level interface12-29
  789. Figure 12-6    A query document dialog box12-47
  790. Figure 12-7    The relationship between resources in a query document and the query record12-49
  791. Figure 12-8    The relationship between a query definition function and queries12-50
  792. Figure 12-9    Structure of a compiled query ('qrsc') resource12-90
  793. Figure 12-10    Structure of a compiled query string ('wstr') resource12-91
  794. Table 12-1    Data types defined by the Data Access Manager12-38
  795. Listing 12-1    Using the high-level interface12-18
  796. Listing 12-2    Two completion routines12-21
  797. Listing 12-3    A sample status routine12-26
  798. Listing 12-4    Sending a query fragment12-31
  799. Listing 12-5    Using the low-level interface12-33
  800. Listing 12-6    A result handler12-45
  801. Listing 12-7    A query definition function12-52
  802. About This Book
  803.  
  804.  
  805. This book, Inside Macintosh: Interapplication Communication, describes the interapplication communication architecture, which provides a standard and extensible mechanism for communication among Macintosh applications. This book also describes the system software routines that you can use to implement various forms of interapplication communication in your application.
  806. If you are new to programming on the Macintosh computer, you should read Inside Macintosh: Overview for an introduction to general concepts of Macintosh programming; Inside Macintosh: Macintosh Toolbox Essentials for information on how to use menus, windows, and controls in your application; and Macintosh Human Interface Guidelines for a complete discussion of user interface guidelines and principles that every Macintosh application should follow.
  807. This book describes how to implement publish and subscribe features in your application, how to communicate with other applications using Apple events, how to respond to scripts, and how to exchange information with other applications using the PPC Toolbox. It also discusses how your application can use the Data Access Manager to access information from a database application or other data source.
  808. For an overview of all the features provided by the interapplication communication architecture, see the chapter “Introduction to Interapplication Communication” in this book.
  809. To provide support for publish and subscribe features in your application, see the chapter “Edition Manager” in this book. This chapter describes how your application can allow users to share dynamic data among many documents.
  810. To communicate with other applications by using Apple events, first see the chapter “Introduction to Apple Events” for a general introduction to Apple events. For information on how to respond to the required Apple events, see the chapter “Responding to Apple Events.” To create and send Apple events, see the chapter “Creating and Sending Apple Events.”
  811. You can choose to write your application so that it can recognize descriptions, in Apple events, of objects in the application such as words, paragraphs, shapes, or documents. To do so, see the chapter “Resolving and Creating Object Specifier Records.”
  812. In addition to supporting Apple events, you can make your application scriptable—that is, capable of responding to Apple events sent to it by a scripting component. By executing scripts, users of scriptable applications can automate repetitive tasks or conditional tasks that involve multiple applications. For more general information about scripting, see the chapter “Introduction to Scripting.” See the chapter “Apple Event Terminology Resources” for information on the resources your application needs to provide in order to be scriptable.
  813. You can also make your application recordable, that is, capable of recording a user’s actions for later playback. For more information, see the chapter “Recording Apple Events.”
  814. For information on how your application can execute a script with the aid of a scripting component, see the chapter “Scripting Components.”
  815. Although you’ll usually want to use Apple events to communicate with other applications, if you need low-level control of communication between applications you can use the Program-to-Program Communications (PPC) Toolbox. For more information, see the chapter “Program-to-Program Communications Toolbox.”
  816. Applications can use the Data Access Manager to access information from a database application or other data source. For example, a user in San Francisco might use a spreadsheet application to request data from a company database in New York. The spreadsheet application can use the Data Access Manager to request the data from the database. The database application in New York sends back the requested data, and the spreadsheet application can then use this data to generate a graph of the information. For information on sending and retrieving information from a data source, see the chapter “Data Access Manager.”
  817. For definitions of specific Apple events and Apple event objects, see the Apple Event Registry: Standard Suites, available from APDA.
  818. For information on handling files in your application and a description of aliases and alias records, see Inside Macintosh: Files.
  819. For information on processes and process serial numbers, see Inside Macintosh: Processes.
  820.  
  821. Format of a Typical Chapter
  822.  
  823. Almost all chapters in this book follow a standard structure. For example, the chapter “Creating and Sending Apple Events” contains these sections:
  824. n    “Creating an Apple Event” and “Sending an Apple Event.” These sections describe how your application can create and send Apple events. They describe the Apple Event Manager routines that you can use to accomplish these tasks, give related user interface information, and provide code samples and additional information.
  825. n    “Reference to Creating and Sending Apple Events.” This section provides a complete reference to the Apple Event Manager routines you can use to create and send Apple events. Each routine description also follows a standard format, which presents the routine declaration followed by a description of every parameter of the routine. Some routine descriptions also give additional descriptive information, such as assembly-language information or result codes.
  826. n    “Summary of Creating and Sending Apple Events.” This section provides the Pascal and C interfaces for the constants, data structures, routines, and result codes associated with the Apple Event Manager routines for creating and sending Apple events. It also includes relevant assembly-language interface information.
  827.  
  828. Conventions Used in This Book
  829.  
  830. Inside Macintosh uses various conventions to present information. Words that require special treatment appear in specific fonts or font styles. Certain information, such as the contents of registers, use special formats so that you can scan them quickly.
  831. Special Fonts
  832.  
  833. All code listings, reserved words, and the names of actual data structures, fields, constants, parameters, and routines are shown in Courier (this is Courier).
  834. Words that appear in boldface are key terms or concepts and are defined in the Glossary.
  835. Types of Notes
  836.  
  837. There are several types of notes used in this book.
  838. Note
  839. A note like this contains information that is interesting but possibly not essential to an understanding of the main text. (An example appears on page 3-26.)u
  840. IMPORTANT
  841. A note like this contains information that is essential for an understanding of the main text. (An example appears on page 3-33.)s
  842. sWARNING
  843. Warnings like this indicate potential problems that you should be aware of as you design your application. Failure to heed these warnings could result in system crashes or loss of data. (An example appears on page page 4-10.)s
  844. Assembly-Language Information
  845.  
  846. Some chapters provide additional assembly-language information. For example, Inside Macintosh provides information about the registers for specific routines like this:
  847. Registers on entry        
  848. A0    Contents of register A0 on entry    
  849.  
  850. Registers on exit        
  851. D0    Contents of register D0 on exit    
  852.  
  853. In addition, Inside Macintosh provides information about the fields of a parameter block in this format:
  854. ´    inAndOut    Integer    Input/output parameter.    
  855. ¨    output1    Ptr    Output parameter.    
  856. Æ    input1    Ptr    Input parameter.    
  857.  
  858. The arrow in the far left column indicates whether the field is an input parameter, output parameter, or both. You must supply values for all input parameters and input/output parameters. The routine returns values in output parameters and input/output parameters.
  859. The second column shows the field name as defined in the MPW Pascal interface files; the third column indicates the Pascal data type of that field. The fourth column provides a brief description of the use of the field. For a complete description of each field, see the discussion that follows the parameter block or the description of the parameter block in the reference section of the chapter.
  860.  
  861. The Development Environment
  862.  
  863. The system software routines described in this book are available using Pascal, C, or assembly-language interfaces. How you access these routines depends on the development environment you are using. When showing system software routines, this book uses the Pascal interface available with the Macintosh Programmer’s Workshop (MPW).
  864. All code listings in this book are shown in Pascal (except for listings that describe resources, which are shown in Rez-input format). They show methods of using various routines and illustrate techniques for accomplishing particular tasks. All code listings have been compiled and, in many cases, tested. However, Apple Computer, Inc., does not intend for you to use these code samples in your application. You can find the location of code listings in the list of figures, tables, and listings. If you know the name of a particular routine (such as MyHandleODoc or MyHandleQuit) shown in a code listing, you can find the page on which the routine occurs by looking under the entry “sample routines” in the index of this book.
  865. In order to make the code listings in this book more readable, they show only limited error handling. You need to develop your own techniques for handling errors. 
  866. This book occasionally illustrates concepts by reference to sample applications called SurfWriter, SurfDB, and SurfCharter; these are not actual products of Apple Computer, Inc.
  867. APDA is Apple’s worldwide source for over three hundred development tools, technical resources, training products, and information for anyone interested in developing applications on Apple platforms. Customers receive the quarterly APDA Tools Catalog featuring all current versions of Apple development tools and the most popular third-party development tools. Ordering is easy; there are no membership fees, and application forms are not required for most of our products. APDA offers convenient payment and shipping options, including site licensing.
  868. To order products or to request a complimentary copy of the APDA Tools Catalog, contact
  869. APDA 
  870. Apple Computer, Inc. 
  871. P.O. Box 319
  872. Buffalo, NY 14207-0319Telephone    800-282-2732 (United States)
  873. 800-637-0029 (Canada)
  874. 716-871-6555 (International)    
  875. Fax    716-871-6511     
  876. AppleLink    APDA    
  877. America Online    APDA    
  878. CompuServe    76666,2405    
  879. Internet    APDA@applelink.apple.com    
  880.         
  881. If you provide commercial products and services, call 408-974-4897 for information on the developer support programs available from Apple.
  882. For information on registering signatures, file types, and other technical information, contact
  883. Macintosh Developer Technical Support
  884. Apple Computer, Inc.
  885. 20525 Mariani Avenue, M/S 75-3T
  886. Cupertino, CA 95014-6299
  887. The Apple Event Registrar maintains the Apple Event Registry: Standard Suites and other information about the ongoing development of Apple event suites. For more information about Apple event suites, including those under development, send electronic mail to the AppleLink address REGISTRY.
  888. Listing 1-0
  889. Table 1-0
  890. Introduction to Interapplication Communication
  891. Contents
  892. Overview of Interapplication Communication1-3
  893. Sharing Data Among Applications1-6
  894. Sending and Responding to Apple Events1-9
  895. Standard Apple Events1-10
  896. Handling Apple Events1-12
  897. Supporting AppleScript and Other Scripting Languages1-13
  898. Scriptable Applications1-16
  899. Recordable Applications1-18
  900. Applications That Manipulate and Execute Scripts1-19
  901. Exchanging Message Blocks1-22
  902. Introduction to Interapplication Communication
  903. This chapter describes the interapplication communication (IAC) architecture for Macintosh computers, summarizes how your application can take advantage of it, and tells you where in this book to find the information you need to perform specific tasks.
  904. The Apple Event Manager, Event Manager, and Program-to-Program Communications (PPC) Toolbox underlie all the IAC tasks your application can perform. This chapter introduces the Apple Event Manager and the Program-to-Program Communications Toolbox. For information about the Event Manager, see Inside Macintosh: Macintosh Toolbox Essentials. For definitions of the standard Apple events available for use by all applications, see the Apple Event Registry: Standard Suites.
  905. The IAC architecture includes the Open Scripting Architecture (OSA). The OSA provides a mechanism that allows users to control multiple applications by means of scripts, or sets of instructions, written in a variety of scripting languages. Each scripting language has a corresponding scripting component that is managed by the Component Manager. When a user executes a script, the scripting component sends Apple events to one or more applications to perform the actions the script describes.
  906. This chapter introduces the OSA and describes how to make your application scriptable, or capable of responding to Apple events sent to it by a scripting component. 
  907. For more information about using the Component Manager, see Inside Macintosh: More Macintosh Toolbox.
  908.  
  909. Overview of Interapplication Communication
  910.  
  911. The interapplication communication (IAC) architecture provides a standard and extensible mechanism for communication among Macintosh applications. The IAC architecture makes it possible for your application to
  912. n    provide automated copy and paste operations between your application and other applications
  913. n    be manipulated by means of scripts
  914. n    send and respond to Apple events
  915. n    send and respond to high-level events other than Apple events
  916. n    read and write blocks of data between applications
  917. The chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials describes how your application can use Event Manager routines to send and respond to high-level events. High-level events need not adhere to any specific protocol, so their interpretation is defined by each application that sends or receives them.
  918. The most important requirement for high-level communication among all applications is a common vocabulary of events. To provide such a standard, Apple Computer, Inc., has defined a protocol called the Apple Event Interprocess Messaging Protocol (AEIMP). High-level events that conform to this protocol are called Apple events. 
  919. The vocabulary of publicly available Apple events is published in the Apple Event Registry: Standard Suites, which defines the standard Apple events that developers and Apple have worked out for use by all applications. To ensure that your application can communicate at a high level with other applications that support Apple events now and in the future, you should support the standard Apple events that are appropriate for your application. 
  920. Effective IAC requires close cooperation among applications at several levels. In addition to the format for high-level events and the standard vocabulary of Apple events, Apple has defined several other standards your application can use to communicate with other applications. These include standard methods for dealing with shared dynamic data, scripts, and low-level message blocks. 
  921. The IAC architecture comprises the following parts: 
  922. n    The Edition Manager allows applications to automate copy and paste operations between applications, so that data can be shared dynamically.
  923. n    The Open Scripting Architecture (OSA) provides a standard mechanism, based on the Apple Event Manager, that allows users to control multiple applications by means of scripts written in a variety of scripting languages.
  924. n    The Apple Event Manager allows applications to send and respond to Apple events.
  925. n    The Event Manager allows applications to send and respond to high-level events other than Apple events.
  926. n    The Program-to-Program Communications (PPC) Toolbox allows applications to exchange blocks of data with each other by reading and writing low-level message blocks. It also provides a standard user interface that allows a user working in one application to select another application with which to exchange data.
  927. Figure 1-1 shows the primary relationships among these parts. The managers and components toward the top of the figure rely on the managers beneath them. The Edition Manager uses the services of the Apple Event Manager to support dynamic data sharing. Scripting components manipulate and execute scripts with the aid of the Apple Event Manager. The Apple Event Manager in turn relies on the Event Manager to send Apple events as high-level events, and the Event Manager uses the services of the PPC Toolbox. 
  928. Figure 1-1 also shows the five principal means of communication provided by the IAC architecture. In addition to using the Edition Manager and scripting components to send Apple events on their behalf, applications can use the Apple Event Manager directly to send Apple events to other applications. All applications can use the Apple Event Manager to respond appropriately to Apple events, whether they are sent by the Edition Manager, a scripting component, or other applications. Applications can also use the Event Manager directly to send or receive high-level events other than Apple events, and the PPC Toolbox directly to send or receive blocks of data.
  929. Figure 1-1    Principal methods of communication between applications
  930.  
  931. The five forms of IAC shown in Figure 1-1 can be summarized as follows:
  932. n    Sharing dynamic data. The Edition Manager allows users to copy data from one application’s document to another application’s document, updating information automatically when the data in the original document changes. The verbs publish and subscribe describe this form of dynamic data sharing, and the noun edition describes a copy of the data to be shared. Applications that support dynamic data sharing must implement the Create Publisher and Subscribe To menu commands. The Edition Manager provides the interface that allows applications to share editions.
  933. You can let users publish and subscribe on a local volume or across a network. In general, users should be able to publish or subscribe to anything that they can copy or paste. “Sharing Data Among Applications,” which begins on page 1-6, describes how you can use the publish and subscribe features in your application.
  934. n    Scripting. The OSA includes the Apple Event Manager, the Apple events defined by the Apple Event Registry: Standard Suites, and the routines supported by scripting components, which applications can use via the Component Manager to execute scripts. Script-editing applications such as Script Editor (not shown in Figure 1-1) allow users to manipulate and execute scripts. 
  935. Each scripting language has a corresponding scripting component that can execute scripts written in that language. Scripting components typically implement a text-based scripting language based on Apple events. For example, the AppleScript component implements AppleScript, the standard user scripting language defined by Apple Computer, Inc. When the AppleScript component executes a script, it performs the actions described in the script, including sending Apple events to applications when necessary. 
  936. “Supporting AppleScript and Other Scripting Languages,” which begins on page 1-13, describes how the OSA makes it possible for your application to 
  937. n    provide human-language equivalents to Apple event codes so that scripting components can send your application the appropriate Apple events during script execution
  938. n    allow users to record their actions in the form of a script
  939. n    manipulate and execute scripts
  940. n    Sending and responding to Apple events. Your application can send Apple events directly to other applications to request services or information or to provide information. To support AppleScript and most other scripting languages based on the OSA, your application must be able to respond to Apple events. “Sending and Responding to Apple Events,” which begins on page 1-9, describes how applications can send and respond to Apple events with the aid of the Apple Event Manager.
  941. n    Sending and responding to other high-level events. The Event Manager allows applications to support high-level events other than Apple events. See the chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials for information about high-level events.
  942. n    Exchanging message blocks. The PPC Toolbox allows applications to exchange blocks of data with each other by reading and writing low-level message blocks. This method of communication is most useful for applications that are closely integrated, specifically designed to work together, or dependent on each other for information. It can also be used in code that is not event-based. See “Exchanging Message Blocks” on page 1-22 for a summary of the capabilities provided by the PPC Toolbox.
  943. All forms of IAC are based on the premise that applications cooperate with each other. Both the application sending a high-level event or low-level message block and the application receiving it must agree on the protocol for communication. You can ensure effective high-level communication between your application and other Macintosh applications by supporting the standard Apple events defined in the Apple Event Registry: Standard Suites. 
  944.  
  945. Sharing Data Among Applications
  946.  
  947. All Macintosh applications can use the Scrap Manager to share static data by allowing the user to copy and paste data between documents. Dynamic data sharing, or automated copy and paste operations between applications, extends this capability to dynamically changing data. The Edition Manager lets applications share dynamic data at the user’s request. You incorporate publish and subscribe capabilities in your application much as you incorporate copy and paste capabilities.
  948. A user can publish data by selecting a portion of text, graphics, or other data in a document and choosing Create Publisher from the Edit menu. In response, your application saves the selected information in a separate file. This stored information is referred to as an edition. The user can subscribe to an edition by choosing Subscribe To from the Edit menu; when the user selects a file that contains an edition, your application includes the information from the edition in the current document. The information in an edition can be shared by many documents.
  949. Figure 1-2 shows the principal relationships among the Edition Manager, the publishing application, the subscribing application, and the file that contains the edition. In addition to the relationships illustrated in the figure, the Edition Manager uses the Apple Event Manager to communicate with applications that are sharing dynamic data.
  950. Figure 1-2    Sharing data with the aid of the Edition Manager
  951.  
  952. A publisher is a portion of a document that is made available to other documents through an edition. A subscriber is a portion of a document that reads the information from an edition. 
  953. Figure 1-3 shows a document containing a publisher, a file containing an edition, and a document containing a subscriber. The bottom fish in the Fishes of the World document is a publisher. The information from this publisher is made available to other documents through the Illustration edition. The Aquarium poster document contains a subscriber that gets its information from the Illustration edition. Note that when a user selects a publisher or subscriber within a document, your application should display a border surrounding the publisher or subscriber.
  954. In general, when a user modifies the contents of a publisher and saves the document, your application should write the new data to the edition. The Edition Manager then uses the Apple Event Manager to inform all open applications with subscribers to the edition that it has been updated. These applications can then automatically update the subscribers in the documents.
  955. Figure 1-3    A publisher, an edition, and a subscriber
  956.  
  957. For example, suppose the user changes the color of the fish in the Fishes of the World document shown in Figure 1-3, then saves the document. This automatically changes the Illustration edition, and the subscribing application can update the Aquarium poster document if that’s what the user wants to do.
  958. Figure 1-4 shows how a user might create a poster from information contained in other documents.
  959. Figure 1-4    Sharing dynamic data with other applications
  960.  
  961. Your application should save the new information in the edition whenever the user edits the publisher and saves the document that contains the publisher—unless the user has indicated that the information should be saved in the edition on request only. When the user saves new information in an edition, the Edition Manager replaces the previous contents.
  962. When an edition is updated, the Edition Manager informs your application. Your application should then update any subscribers (unless the user has indicated that updates should be incorporated on request only).
  963. For example, suppose a user opens a word-processing document called My Stocks that accesses information from an edition called Stock Report. The Stock Report edition might be updated twice a day by an online database. As the information in the edition changes, the My Stocks document can receive automatic updates with the latest information.
  964. You can implement publish and subscribe capabilities in your application by using the routines provided by the Edition Manager and supporting the related Apple events. The chapter “Edition Manager” in this book provides sample code that shows how to add these features to your application. The chapter “Responding to Apple Events” in this book describes how to support the related Apple events. 
  965.  
  966. Sending and Responding to Apple Events
  967.  
  968. An Apple event is a high-level event that conforms to the Apple Event Interprocess Messaging Protocol. The Apple Event Manager uses the Event Manager to send Apple events between applications on the same computer or between applications on remote computers.   
  969. Applications typically use Apple events to request services and information from other applications or to provide services and information in response to such requests. For example, any application can use the Get Data Apple event to request that your application locate and return a particular set of data, such as a table. If your application supports the Get Data event, it should be able to recognize the event and respond by locating the requested data and returning a copy of the data to the application that requested it.  
  970. Communication between two applications that support Apple events is initiated by a client application, which sends an Apple event to request a service or information. For example, a client application might request services such as printing specific files, checking the spelling of a list of words, or performing a numeric calculation; or it might request information, such as one customer’s address or a list of names and addresses of all customers living in Ohio. The application providing the service or the requested information is called a server application. The client and server applications can reside on the same local computer or on remote computers connected to a network. 
  971. Figure 1-5 shows the relationships among a client application, the Apple Event Manager, and a server application. The client application uses Apple Event Manager routines to create and send the Apple event, and the server application uses Apple Event Manager routines to interpret the Apple event and respond appropriately. If the client application so requests, the server application adds information to a reply Apple event that the Apple Event Manager returns to the client application. 
  972. Figure 1-5    Sending and responding to Apple events with the aid of the Apple Event Manager
  973.  
  974. If an Apple event is one of the standard events defined in the Apple Event Registry: Standard Suites, the client application can construct the event and the server application can interpret it according to the standard definition for that event. To ensure that your application can respond to Apple events sent by other applications, you should support the standard Apple events that are appropriate for your application.
  975. Standard Apple Events
  976.  
  977. The current edition of Apple Event Registry: Standard Suites defines the standard suites of Apple events, which are groups of related events that are usually implemented together. The Apple Event Registrar maintains the Apple Event Registry: Standard Suites and other information about the ongoing development of Apple event suites. 
  978. The standard suites include the following:  
  979. n    The Required suite consists of the four Apple events that the Finder sends to applications. These events are Open Application, Open Documents, Print Documents, and Quit Application. The Finder uses the required events as part of the mechanisms in System 7 and later versions for launching and terminating applications. To support System 7, your application must support the required Apple events as described in the chapter “Responding to Apple Events” in this book.  
  980. n    The Core suite consists of the basic Apple events, including Get Data, Set Data, Move, Delete, and Save, that nearly all applications use to communicate. You should support the Apple events in the Core suite that make sense for your application. 
  981. n    A functional-area suite consists of a group of Apple events that support a related functional area. Functional-area suites include the Text suite and the Database suite. You can decide which functional-area suites to support according to which features your application provides. For example, most word-processing applications should support the Text suite, and most database applications should support the Database suite.
  982. You do not need to implement all Apple events at once. You should begin by supporting the required Apple events, then add support for the events sent by the Edition Manager, the core events, and the functional-area events as appropriate for your application. 
  983. If necessary, you can extend the definitions of the standard Apple events to suit specific capabilities of your application. You can also define your own custom Apple events. However, only those applications that choose to support your custom Apple events explicitly will be able to make use of them. If all applications communicated solely by means of custom Apple events, every application would have to support all other applications’ custom events. Instead of creating custom Apple events, try to use the standard Apple events and extend their definitions as necessary.
  984. Apple events describe actions to be performed by the applications that receive them. In addition to a vocabulary of actions, or “verbs,” effective communication between applications requires a method of referring to windows, data (such as words or graphic elements), files, folders, volumes, zones, and other items on which actions can be performed. The Apple Event Manager provides a method for specifying structured names, or “noun phrases,” that applications can use to describe the objects on which Apple events act. 
  985. The Apple Event Registry: Standard Suites includes definitions for Apple event object classes, which are simply names for objects that can be acted upon by each kind of Apple event. Applications use these definitions and Apple Event Manager routines to create complex descriptions of almost any discrete item in another application or its documents. For example, an application could use Apple Event Manager routines and standard object class definitions to construct a Get Data event that requests “the most recent invoice to John Chapman in the Invoices database on the Archives server in the Accounting zone” and send the event to the appropriate application across the network.
  986. An Apple event object is any item supported by an application, such as a word, paragraph, shape, or document, that can be described in an Apple event. In the example just given, the specified invoice, the Invoices database, the Archives server, and the Accounting zone are nested Apple event objects. Nearly any item that a user can differentiate and manipulate on a Macintosh computer can be described as an Apple event object of a specified object class nested within other Apple event objects. When handling an Apple event that includes such a description, an application must locate the specified Apple event object and perform the requested action on it.  
  987. Most of the standard Apple events defined in the Apple Event Registry: Standard Suites require your application to recognize specific Apple event object classes. Support for the standard Apple events, including Apple event object classes, allows your application to respond to requests for services or information from any other application or process. 
  988. Handling Apple Events
  989.  
  990. Figure 1-6 shows a common Apple event from the Core suite, the Set Data event. The SurfDB application is the client; it sends a Set Data event to the SurfCharter application. This event requests that SurfCharter use some new sales figures generated by SurfDB to update the data for the chart named “Summary of Sales” in the document named “Sales Chart.” The Apple event contains information that identifies an action—setting data—and a description of the Apple event object on which to perform the action—“the chart named Summary of Sales in the document named Sales Report.” The Apple event also includes the new data for the chart.  
  991. Figure 1-6    A Set Data event
  992.  
  993. To respond appropriately, the SurfCharter application in Figure 1-6 can use the Apple Event Manager to determine what kind of Apple event has been sent and pass the event to the appropriate Apple event handler. An Apple event handler is an application-defined function that extracts pertinent data from an Apple event, performs the requested action, and returns a result. In this case, the Set Data event handler must locate an Apple event object—that is, the specified chart in the specified document—and change the data displayed in the chart as requested. 
  994. The Apple Event Manager provides routines that a server application can use in its Apple event handlers to take apart an Apple event and examine its contents. The SurfCharter application in Figure 1-6 can interpret the contents of the Set Data Apple event according to the definition of that event in the Apple Event Registry: Standard Suites. The Set Data event handler uses both Apple Event Manager routines and the SurfCharter application’s own routines to locate the chart and make the requested change.
  995. The Apple Event Manager also provides routines that a client application can use to construct and send an Apple event. However, the most important requirement for applications that support IAC is the ability to respond to Apple events, because this ability is essential for an application that users can control through scripts. The next section describes how you can use Apple events to support scripting in your application.
  996. The chapter “Introduction to Apple Events” in this book provides an overview of Apple events and describes how you can use the Apple Event Manager to implement Apple events in your application. The chapters “Responding to Apple Events,” “Creating and Sending Apple Events,” “Resolving and Creating Object Specifier Records,” and “Recording Apple Events” provide detailed information about the Apple Event Manager.  
  997.  
  998. Supporting AppleScript and Other Scripting Languages
  999.  
  1000. A script is any collection of data that, when executed by the appropriate program, causes a corresponding action or series of actions. For example, some database, telecommunications, and page-layout applications allow users to automate repetitive or conditional tasks by means of scripts written in proprietary scripting languages. The HyperTalk® scripting language allows users to control the behavior of HyperCard® stacks. Macro programs can automate tasks at the level of mouse clicks and keystrokes.   
  1001. The Open Scripting Architecture (OSA) provides a standard mechanism that allows users to control multiple applications with scripts written in a variety of scripting languages. Each scripting language has a corresponding scripting component. When a scripting component executes a script, it performs the actions described in the script, including sending Apple events to applications if necessary. 
  1002. The OSA comprises the following parts:
  1003. n    The Apple Event Manager allows applications to respond to Apple events sent by scripting components (see the previous section, “Sending and Responding to Apple Events”).
  1004. n    The Apple Event Registry: Standard Suites defines the standard vocabulary of Apple events.
  1005. n    The standard scripting component data structures, routines, and resources allow applications to interact with any scripting component. 
  1006. n    The AppleScript component implements the AppleScript scripting language.
  1007. The AppleScript component, which implements the AppleScript scripting language, is the implementation of the OSA provided by Apple Computer, Inc. Users can view a script written in the AppleScript scripting language in several different dialects, or versions of the AppleScript language that resemble specific human languages or programming languages.
  1008. Figure 1-7 shows the relationships among some of these parts. The client application in Figure 1-7 is Script Editor, an application provided by Apple Computer, Inc., that allows users to record, edit, and execute scripts. The client application could also be any other application that uses the standard scripting component routines to execute scripts. Script Editor uses the Component Manager to open a connection with the scripting component that created the script to be executed. 
  1009. Figure 1-7    How a scripting component executes a script
  1010.  
  1011. Like sound resources, scripts can be stored in applications and documents as well as in distinct script files that can be manipulated from the Finder. Script Editor allows users to execute scripts stored in script files. Users can also execute special script files called script applications simply by opening them from the Finder. 
  1012. During script execution, scripting components perform actions described in the script, using the Apple Event Manager to send Apple events when necessary. The server applications shown in Figure 1-7 use the Apple Event Manager to examine the contents of the Apple events they receive and to respond appropriately. A server application always responds to the same Apple event in the same way, regardless of whether the event is sent by a scripting component or directly by a client application. 
  1013. You can take advantage of the OSA in three ways:
  1014. n    You can make your application scriptable, or capable of responding to Apple events sent to it by a scripting component. An application is scriptable if it
  1015. n    Responds to the appropriate standard Apple events. See the previous section, “Sending and Responding to Apple Events.”
  1016. n    Provides an Apple event terminology extension ('aete') resource that describes which Apple events your application supports and the corresponding human-language terminology for use in scripts. The 'aete' resource allows scripting components to interpret scripts correctly and send the appropriate Apple events to your application during script execution. 
  1017. By executing scripts, users of scriptable applications can perform almost any task that they would otherwise perform by choosing menu commands, typing, and so on. Users can also execute scripts to perform many tasks that might otherwise be difficult to accomplish, especially repetitive or conditional tasks that involve multiple applications.
  1018. n    You can make your application recordable—that is, capable of sending Apple events to itself in response to user actions such as choosing a menu command or changing the contents of a document. After a user has turned on recording for a particular scripting component, the scripting component receives copies of all subsequent Apple events and records them in the form of a script. 
  1019. n    You can have your application manipulate and execute scripts with the aid of a scripting component. To do so, your application must
  1020. n    use the Component Manager to open a connection with the appropriate component
  1021. n    use the standard scripting component routines to record, edit, compile, save, load, or execute scripts when necessary
  1022. Users of applications that execute scripts can modify the applications’ behavior by editing the scripts. For example, a user of an invoice program might be able to write a script that checks and if necessary updates customer information in a separate database application each time the user posts an invoice.
  1023. The sections that follow describe these three kinds of scripting capabilities in more detail. The chapter “Introduction to Scripting” in this book provides an overview of the way scripting components work and how you can implement support for scripting in your application.
  1024. Scriptable Applications
  1025.  
  1026. If your application can respond to standard Apple events sent by other applications, it can also respond to the same Apple events sent by a scripting component. Before executing a script that controls your application, a scripting component must associate the human-language terms used in the script with specific Apple event codes supported by your application. Scriptable applications provide this information in an Apple event terminology extension ('aete') resource.   
  1027. Because scripting components can obtain information from 'aete' resources about the nature of different applications’ support for Apple events, a single script can describe complex tasks performed cooperatively by several specialized applications. For example, a user can execute an AppleScript script to locate all records in a database with specific characteristics, update a series of charts based on those records, import the charts into a page-layout document, and send the document to a remote computer on the network via electronic mail. 
  1028. When a user executes such a script, the AppleScript component attempts to perform the actions the script describes, including sending Apple events to various applications when necessary. To map human-language terms used in the script to the corresponding Apple events supported by each application, the AppleScript component looks up the terms in the applications’ 'aete' resources. Each human-language term specified by an application’s 'aete' resource has a corresponding Apple event code. After the AppleScript component has identified the Apple event codes for the terms used in a script, it can create and send the Apple events that perform the actions described in the script.
  1029. To respond appropriately to the Apple events sent to it by the AppleScript component, the database application in this example must be able to locate records with specific characteristics so that it can identify and return the requested data. The other applications involved must support Apple events that perform the other actions described in the script.
  1030. One line in such a script might be a statement like this:
  1031. copy Totals to chart "Summary of Sales" of document "Sales Chart"
  1032. In this statement, the word Totals is a variable that has been set earlier in the same script to the value of the new data generated by a database application. The statement causes the AppleScript component to send a Set Data event updating the chart named “Summary of Sales.” Figure 1-8 shows how the AppleScript component would execute this statement. (Figure 1-6 on page 1-12 shows a database application that sends a similar Set Data event directly.) 
  1033. To interpret the terms in this script statement correctly, the AppleScript component must be able to look them up in the SurfCharter application’s 'aete' resource, which maps those terms to the corresponding codes for Apple events, object classes, and so on used by the Apple Event Manager. The AppleScript component can then create and send the Set Data event to SurfCharter.
  1034. When it receives the Set Data event, the SurfCharter application uses the Apple Event Manager to determine what kind of Apple event has been sent and to pass the event to SurfCharter’s handler for that event, which in turn locates the chart and changes its data as requested.
  1035. The chapter “Introduction to Scripting” in this book describes how the 'aete' resource works. The chapter “Apple Event Terminology Resources” describes how to define terminology for use by the AppleScript component and how to create an 'aete' resource.
  1036. Figure 1-8    A Set Data event sent during script execution
  1037.  
  1038. Recordable Applications
  1039.  
  1040. If you decide to make your application scriptable, you can also make it recordable, allowing users to record their actions in your application in the form of a script. Even users with little or no knowledge of a particular scripting language can record their actions in recordable applications in the form of a script. More knowledgeable users can record scripts and then edit or combine them as desired.  
  1041. Applications generally have two parts: the code that implements the application’s user interface and the code that actually performs the work of the application when the user manipulates the interface. To make your application fully recordable, you should separate these two parts of your application, using Apple events to connect user actions with the work your application performs. 
  1042. Any significant user action within a recordable application should generate Apple events that a scripting component can record as statements in a script. For example, when a user chooses New from the File menu, a recordable application sends itself a Create Element event, and the application’s handler for that event creates the new document. Implementing Apple events in this manner is called factoring your application. A factored application acts as both the client and the server application for the Apple events it sends to itself. 
  1043. In general, a recordable application should generate Apple events for any user action that could be reversed by the Undo command. A recordable application can usually handle a greater variety of Apple events than it can record, since it must record the same action the same way every time even though Apple events might be able to trigger that action in several different ways.
  1044. A recordable event is any Apple event that any recordable application sends to itself while recording is turned on for the local computer (with the exception of events that the application indicates it does not want to be recorded). After a user turns on recording from the Script Editor application, the Apple Event Manager sends copies of all recordable events to Script Editor. A scripting component previously selected by the user handles each copied event for Script Editor by translating the event into the scripting component’s scripting language and recording the translation as part of a Script Editor script. When a scripting component executes a recorded script, it sends the corresponding Apple events to the applications in which they were recorded.
  1045. Figure 1-9 illustrates how Apple event recording works. The user performs a significant action (such as choosing New from the File menu), and the SurfCharter application sends itself an Apple event to perform the task associated with that action. If recording is turned on, the Apple Event Manager automatically sends a copy of each recordable Apple event to the application (for example, Script Editor) that initiated recording. The scripting component handles the copy of each recordable event by translating it and recording it as part of a script. To translate each Apple event correctly, the scripting component must first check what equivalent human-language terminology the SurfCharter application uses for that Apple event. The scripting component then records the equivalent statement in the script.
  1046. The chapter “Recording Apple Events” in this book describes the Apple Event Manager’s recording mechanism in more detail and explains how to use Apple events to factor your application.
  1047. Figure 1-9    Recording user actions in a factored application
  1048.  
  1049. Applications That Manipulate and Execute Scripts
  1050.  
  1051. Like sound resources, scripts can be stored either as separate files with their own icons in the Finder or within an application or its documents. Your application can store and execute scripts regardless of whether it is scriptable or recordable. If your application is scriptable, however, it can execute scripts that control its own behavior, thus acting as both the client application and the server application for the corresponding Apple events. 
  1052. Your application can establish a connection with any scripting component that is registered with the Component Manager on the same computer. Each scripting component can manipulate and execute scripts written in the corresponding scripting language (or, as in the case of AppleScript, one of the scripting language’s dialects) when your application calls the standard scripting component routines.
  1053. You can use the standard scripting component routines to 
  1054. n    get a handle to a script so you can save the script in a preferences file, in the data fork of a document, or as a separate script file
  1055. n    manipulate scripts associated with any part of your application or its documents, including both Apple event objects and other objects defined by the application
  1056. n    let users record and edit scripts
  1057. n    compile and execute scripts
  1058. Figure 1-10 shows how an application might execute a script that controls its own behavior. The appropriate user action handler executes the script in response to a user action, which can be almost anything: choosing a menu command, clicking a button, tabbing from one table cell to another, and so on. The script might consist of a single statement that describes some default action, such as saving or printing, or a series of statements that describe a series of tasks, such as setting default preferences or styles. Figure 1-10 shows a script that corresponds to a single Apple event, but the script could just as easily correspond to a whole series of Apple events. If your application allows users to modify such a script, they can modify the behavior of your application to suit their needs.
  1059. Figure 1-10    Controlling an application’s own behavior by executing a script
  1060.  
  1061. Your application can associate a script with any Apple event object or application-defined object and execute the script when that object is manipulated in some way. The script can describe actions to be taken by your application, as in 
  1062. Figure 1-10, or actions to be taken by several applications. For example, a user of a word-processing application might attach a script to a specific word so that the application executes the script whenever that word is double-clicked. Such a script could trigger Apple events that look up and display related information from a separate document, run a QuickTime movie, perform a calculation, play a voice annotation, and so on.
  1063. Figure 1-11 shows one way that a script can be used to control two or more applications. When a user chooses the Post Invoice command in the accounting application, the user action handler for that menu command executes a default script for posting an invoice. That script might describe actions such as saving the invoice, updating the sales journal, and so on. The scripting component sends Apple events to the accounting application to perform these actions. 
  1064. Figure 1-11    Posting an invoice and updating a database by executing a script
  1065.  
  1066. The accounting application also allows users to open the default invoice-posting script in Script Editor and modify it so that additional actions are performed when it is executed. For example, as shown in Figure 1-11, the script could instruct the SurfDB application to update a database of customer information in addition to performing the default posting actions. In this case, the scripting component sends Apple events to both the accounting application and SurfDB to carry out all the actions described by the script.
  1067. There is no limit to the actions such a script can describe. In addition to sending the Apple events shown in Figure 1-11, the invoice-posting script could be used to trigger Apple events that cause other applications to perform a credit check, send the invoice to the customer by electronic mail, forward inventory information to a remote server on the network, and so on.
  1068. The chapter “Scripting Components” in this book describes how your application can use the standard scripting component routines to manipulate and execute its own scripts and allow users to modify those scripts.   
  1069.  
  1070. Exchanging Message Blocks
  1071.  
  1072. You should be able to meet most of your application’s IAC needs by using the Apple Event Manager or the Event Manager. However, if you need low-level control or services not provided by the Apple Event Manager or the Event Manager, you can use the PPC Toolbox. The PPC Toolbox lets you send large amounts of data to other applications located on the same computer or across a network. The PPC Toolbox can also be used by pieces of code that are not event-driven. The PPC Toolbox is usually called by the Operating System; device drivers, desk accessories, or other code modules can also use it.
  1073. You cannot use the PPC Toolbox to send data between applications unless both your application and the application you’re communicating with are open at the same time. To initiate communication, one program opens a port and requests a session with another program. The target application must also open a port and accept the request. Once a session is established, the two programs can read and write low-level message blocks. 
  1074. The PPC Toolbox also provides a standard user interface that allows a user working in one application to select another application with which to exchange data, whether the communication is achieved by means of Apple events, other high-level events, or message blocks.
  1075. The chapter “Program-to-Program Communications Toolbox” in this book describes how programs can exchange low-level message blocks.    
  1076. Listing 2-0
  1077. Table 2-0
  1078. Edition Manager
  1079. Contents
  1080. Introduction to Publishers, Subscribers, and Editions2-4
  1081. About the Edition Manager2-12
  1082. Using the Edition Manager2-12
  1083. Receiving Apple Events From the Edition Manager2-13
  1084. Creating the Section Record and Alias Record2-15
  1085. Saving a Document Containing Sections2-19
  1086. Opening and Closing a Document Containing Sections2-22
  1087. Reading and Writing a Section2-24
  1088. Formats in an Edition2-24
  1089. Opening an Edition2-26
  1090. Format Marks2-27
  1091. Reading and Writing Edition Data2-27
  1092. Closing an Edition2-28
  1093. Creating a Publisher2-29
  1094. Creating the Edition Container2-32
  1095. Opening an Edition Container to Write Data2-35
  1096. Creating a Subscriber2-37
  1097. Opening an Edition Container to Read Data2-41
  1098. Choosing Which Edition Format to Read2-41
  1099. Using Publisher and Subscriber Options2-43
  1100. Publishing a New Edition While Saving or Manually2-47
  1101. Subscribing to an Edition Automatically or Manually2-48
  1102. Canceling Sections Within Documents2-48
  1103. Locating a Publisher Through a Subscriber2-49
  1104. Renaming a Document Containing Sections2-50
  1105. Displaying Publisher and Subscriber Borders2-50
  1106. Text Borders2-54
  1107. Spreadsheet Borders2-55
  1108. Object-Oriented Graphics Borders2-56
  1109. Bitmapped Graphics Borders2-57
  1110. Duplicating Publishers and Subscribers2-58
  1111. Modifying a Subscriber2-59
  1112. Relocating an Edition2-60
  1113. Customizing Dialog Boxes2-60
  1114. Subscribing to Non-Edition Files2-62
  1115. Getting the Current Edition Opener2-63
  1116. Setting an Edition Opener2-63
  1117. Calling an Edition Opener2-64
  1118. Opening and Closing Editions2-68
  1119. Listing Files That Can Be Subscribed To2-68
  1120. Reading From and Writing to Files2-68
  1121. Calling a Format I/O Function2-68
  1122. Edition Manager Reference2-71
  1123. Data Structures2-71
  1124. The Edition Container Record2-71
  1125. The Section Record2-72
  1126. Edition Manager Routines2-73
  1127. Initializing the Edition Manager2-74
  1128. Creating and Registering a Section2-74
  1129. Creating and Deleting an Edition Container2-79
  1130. Setting and Getting a Format Mark2-81
  1131. Reading in Edition Data2-83
  1132. Writing out Edition Data2-86
  1133. Closing an Edition After Reading or Writing2-88
  1134. Displaying Dialog Boxes2-90
  1135. Locating a Publisher and Edition From a Subscriber2-98
  1136. Edition Container Formats2-101
  1137. Reading and Writing Non-Edition Files2-102
  1138. Application-Defined Routines2-105
  1139. Summary of the Edition Manager2-106
  1140. Pascal Summary2-106
  1141. Constants2-106
  1142. Data Types2-108
  1143. Edition Manager Routines2-111
  1144. Application-Defined Routines2-113
  1145. C Summary2-114
  1146. Constants2-114
  1147. Data Types2-116
  1148. Edition Manager Routines2-119
  1149. Application-Defined Routines2-122
  1150. Result Codes2-122
  1151.  
  1152. Edition Manager
  1153.  
  1154. This chapter describes how you can use the Edition Manager to allow your users to share and automatically update data from numerous documents and applications.
  1155. The Edition Manager is available only in System 7 or later. It can be used by many different applications located on a single disk or throughout a network of Macintosh computers. To test for the existence of the Edition Manager, use the Gestalt function, described in Inside Macintosh: Operating System Utilities. 
  1156. Read the information in this chapter if you want your application’s documents to share and automatically update data, or if you want to share and automatically update data with documents created by other applications that support the Edition Manager.
  1157. For example, a user might want to capture sales figures and totals from within a spreadsheet and then include this information in a word-processing document that summarizes sales for a given month. The Edition Manager establishes a connection between these two documents. When a user modifies the spreadsheet, the information in the word-processing document can be automatically updated to contain the latest changes. To accomplish this, both the spreadsheet application and the word-processing application must support the features of the Edition Manager.
  1158. To use this chapter, you should be familiar with sending and receiving high-level events, described in the chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials. Your application must also support Apple events to receive Apple events from the Edition Manager. See the following chapters in this book for detailed information on Apple events. 
  1159. The Edition Manager provides you with the ability to
  1160. n    capture data within a document and integrate it into another document
  1161. n    modify information in a document and automatically update any document that shares its data
  1162. n    share information between applications on the same computer or across a network of Macintosh computers
  1163. Building the capabilities of the Edition Manager into your program is similar to building cut-and-paste features into your program. Text, graphics, spreadsheet cells, database reports—any data that you can select, you can make accessible to other applications that support the Edition Manager. The next section provides an overview of the main elements of the Edition Manager. Following sections discuss how to implement these features in your application.
  1164. This chapter also describes an advanced feature that allows applications to share data directly from a file.
  1165.  
  1166.  
  1167. Introduction to Publishers, Subscribers, and Editions
  1168.  
  1169. A section is a portion of a document that shares its contents with other documents. The Edition Manager supports two types of sections: publishers and subscribers. A publisher is a section within a document that makes its data available to other documents or applications. A subscriber is a section within a document that obtains its data from other documents or applications.
  1170. Your application writes a copy of the data in each publisher to a separate file called an edition container. The actual data that is written to the edition container is referred to as the edition. Your application obtains the data for each subscriber by reading data from the edition container. Note that throughout this chapter, the term edition refers to the edition container and the data it contains. 
  1171. You publish data when you want to make it available to other documents and applications. When data is published, it is stored in an edition container. You subscribe to data that a publisher makes available by reading an edition from its container. 
  1172. Note
  1173. Section and edition container are programmatic terms. You should not use them in your application or your documentation. Use publishers, subscribers, and editions. You should also refrain from using other terms such as publication or subscription to describe the dynamic sharing of information provided by the Edition Manager. Use the terms publish and subscribe to describe the Edition Manager features.u
  1174.  
  1175. Each edition has an icon that is visible from the Finder. Figure 2-1 shows the default edition icon.
  1176.  
  1177. Figure 2-1    The default edition icon
  1178.  
  1179. The name that the user specifies for the edition is located next to the edition icon. For information on providing icons for the editions created by your application, see the chapter “Finder Interface” in Inside Macintosh: Macintosh Toolbox Essentials. Figure 2-2 illustrates a document containing a single publisher, its corresponding edition, and a subscriber to the edition in another document.
  1180.  
  1181. Figure 2-2    
  1182. A publisher, an edition, and a subscriber
  1183.  
  1184. Note that the publisher and subscriber borders illustrated in Figure 2-2 may appear slightly different from the borders you see on the screen. Figure 2-6 on page 2-9 shows the publisher and subscriber borders as they appear onscreen.
  1185. Data always flows in one direction, from publisher to edition to subscriber. Documents that contain publishers and subscribers do not have to be open at the same time to share data. Whenever the user saves a document that contains a publisher, the edition changes to reflect the current data from the publisher. All subscribers update their contents from the edition. Any number of subscribers can subscribe to a single edition.
  1186. To create a publisher within a document, a user selects an area of the document to share and chooses Create Publisher from the Edit menu (see Figure 2-7 on page 2-10). Figure 2-3 shows the dialog box that your application should display when the user chooses Create Publisher.
  1187.  
  1188. Figure 2-3    The publisher dialog box
  1189.  
  1190. Your application provides a thumbnail sketch of the edition data, which the Edition Manager displays in the preview area of the publisher dialog box. Your preview of the edition in this dialog box should provide a visual cue about the type of information that the user has selected to publish.
  1191. A preview area also appears in the subscriber dialog box (see Figure 2-4). This preview, too, should provide a visual cue about the type of information the edition contains. For example, it should allow users to distinguish between text information and spreadsheet arrays.
  1192. The publisher dialog box uses the extended interface of the standard file dialog box that accompanies System 7. The user navigates through the contents of the disk using the mouse or keyboard.
  1193. A user can modify a publisher within a document just like any other portion of a document. As a default, each time a user saves a document containing a publisher, your application should automatically write the publisher’s data to the edition. You also need to provide the user with the choice of sending new publisher data to an edition manually (that is, only at the user’s specific request). You should provide these options by using the publisher options dialog box described later in “Using Publisher and Subscriber Options” beginning on page 2-43.
  1194. For example, one user may choose to update an edition automatically each time a document is saved. This update mode is useful for a user who creates a publisher within a spreadsheet application that records stock information. Each time the user updates the stock information and saves the spreadsheet, a new edition automatically becomes available to subscribers.
  1195. Another user may choose to update an edition only upon request. This update mode might be useful for a user who creates a publisher within a word-processing application for a quarterly sales report. The user incrementally updates the sales report throughout the entire quarter but does not want this information to be available to subscribers until the end of the quarter. Only at the end of each quarter does the user specifically request to update the edition and make it available to any subscribers.
  1196. To create a subscriber within a document, the user places the insertion point and chooses Subscribe To from the Edit menu. Figure 2-4 shows the dialog box that your application should display when the user chooses Subscribe To. 
  1197.  
  1198. Figure 2-4    
  1199. The subscriber dialog box
  1200.  
  1201. The subscriber dialog box also uses the extended interface of the standard file dialog box introduced with System 7. Initially, the dialog box should highlight the name of the last edition published or subscribed to. This allows a user to create a publisher and immediately subscribe to its edition.
  1202. A subscriber receives its data from a single edition. By default, your application should automatically update a document containing a subscriber whenever a new edition is available. You also need to provide the user with the choice of receiving the latest edition manually (that is, only when the user specifically requests it). You can provide these options by using the subscriber options dialog box described later in “Using Publisher and Subscriber Options” beginning on page 2-43.
  1203. For example, one user may choose to receive new editions automatically as they become available. This update mode is useful for a user who subscribes to information from an edition that consists of daily sales figures. This user automatically acquires each version of the sales information as it becomes available.
  1204. Another user may choose to receive a new edition only upon request. This update mode is useful for a user who creates a subscriber to an edition that consists of graphics data (such as a company logo). The user may require only periodic versions of the logo and not need frequent updates. In this case, your application should update the subscriber with a new edition only when the user specifically requests it.
  1205. A user can select, cut, copy, or paste an entire subscriber. Although the contents of the subscriber as a whole can be modified, a user cannot edit portions of a subscriber. For example, a user can underline or italicize the entire subscriber text but cannot delete a sentence or rotate a single graphic object. This restriction protects the user from losing changes to a subscriber when a new edition arrives. Remember that, as a default, new editions should automatically update a subscriber. Any changes that a user made to the subscriber text would have to be reapplied by the user when the new edition arrives. See “Modifying a Subscriber” on page 2-59 for further information.
  1206. A single document can contain any number or combination of publishers and subscribers. Figure 2-5 shows an example of a document that contains two publishers and one subscriber (and their corresponding editions). Remember that data always flows in one direction, from publisher to edition to subscriber. The “Concert flyer” document contains a publisher that is subscribed to by the “Benefit concert” document. The “Concert flyer” document also subscribes to a portion of the “Pianos & palm trees” document. In addition, the “Concert flyer” document as a whole is subscribed to by the “Sample flyer” document.
  1207.  
  1208. Figure 2-5    A document and its corresponding editions
  1209.  
  1210. You should distinguish each selected publisher and subscriber within a document with a border. Display a publisher border as three pixels wide with 50 percent gray lines, and display a subscriber border as three pixels wide with 75 percent gray lines. A rectangle of one white pixel should separate the data from the border itself. Borders should be drawn outside the contents of publishers and subscribers so that data is not obscured. See 
  1211. Figure 2-6 for an illustration of the borders as they appear onscreen. See “Displaying Publisher and Subscriber Borders” on page 2-50 for detailed information on how to implement borders for specific applications.
  1212. Figure 2-6 shows a document containing a publisher and a document containing a subscriber, with borders displayed for each.
  1213. Borders for publishers and subscribers should behave like the borders of 'PICT' graphics within a word-processing document. Your application should display a border whenever the user clicks within the content area of a publisher or a subscriber. Your application should hide the border whenever the user clicks outside the content area. See “Displaying Publisher and Subscriber Borders” on page 2-50 for detailed information on how to implement borders for specific applications.
  1214.  
  1215. Figure 2-6    Publisher and subscriber borders
  1216.  
  1217. You also need to support the standard Edition Manager menu commands in the Edit menu. These menu items include
  1218. n    Create Publisher…
  1219. n    Subscribe To…
  1220. n    Publisher/Subscriber Options…
  1221. n    Show/Hide Borders (optional)
  1222. n    Stop All Editions (optional)
  1223. Use a divider to separate the Edition Manager menu commands from the standard Edit menu commands Cut, Copy, and Paste. Figure 2-7 shows the standard Edition Manager menu commands.
  1224.  
  1225. Figure 2-7    Edition Manager commands in the Edit menu
  1226.  
  1227. The Subscriber Options menu command should toggle with the Publisher Options menu command. When a user selects a subscriber and then accesses the menu bar, your application should adjust its menus so that the Subscriber Options menu command appears in the Edit menu. When a user selects a publisher and then accesses the menu bar, your application should adjust its menus so that the Publisher Options menu command appears in the Edit menu. In addition, you may support a Show Borders menu command that toggles with Hide Borders to display or hide all publishers and subscriber borders within documents. You may also support a Stop All Editions menu command to provide a method for temporarily suspending all update activity in a document. When the user chooses this command, you should place a checkmark next to it. You should also stop all publishers from sending data to editions and all subscribers from receiving new editions. When the user chooses this command again, remove the checkmark and update any subscribers that are set up to receive new editions automatically.
  1228. If you find that you need all of the available space in the Edit menu for your application’s commands, you may create a hierarchical menu for the Edition Manager menu commands. If you choose to implement this structure, you should allow users to access the Edition Manager menu commands through a Publishing menu command in the Edit menu. Because this menu structure is not as accessible to users, you should implement it only if you have no other alternative.
  1229. Figure 2-8 shows the Edition Manager menu commands in a hierarchical menu structure.
  1230.  
  1231. Figure 2-8    Edition Manager commands under the Publishing menu command
  1232.  
  1233. For each publisher or subscriber within an open document, you must have a section record and an alias record. The section record contains a time stamp that records the version of the data that resides in the section. The section record also identifies the section as either a publisher or subscriber, and it establishes a unique identity for each publisher or subscriber. The section record does not contain the data within the section. The alias record is a reference to the edition container from the document that contains the corresponding publisher or subscriber section.
  1234. There are special options associated with publishers and subscribers within documents. Your application can use the publisher and subscriber options dialog boxes provided by the Edition Manager to make these choices available to the user. For example, a user can select Open Publisher within the subscriber options dialog box to access the document containing the publisher. Your application can also allow a user to cancel subscribers or publishers within documents, specify when to update an edition from a publisher, or specify when to update a subscriber with a new edition. These options are described in “Using Publisher and Subscriber Options” beginning on page 2-43.
  1235.  
  1236.  
  1237. About the Edition Manager
  1238.  
  1239. The next section discusses how to save, open, read, and write a document that shares data. In addition, it describes how to
  1240. n    make data accessible to other applications
  1241. n    integrate data into numerous documents
  1242. n    set update options
  1243. n    implement borders
  1244. n    modify shared data
  1245. n    customize dialog boxes
  1246. n    subscribe to data in non-edition files
  1247.  
  1248. Using the Edition Manager
  1249.  
  1250. This section describes how your application can
  1251. n    receive Apple events from the Edition Manager
  1252. n    set up a section record and alias record for open documents containing sections
  1253. n    save a document that contains sections
  1254. n    open a document that contains sections
  1255. n    read and write sections
  1256. n    create a publisher within a document, create its edition container, and write data to it
  1257. n    create a subscriber within a document and read its data from an edition
  1258. To begin, you must determine whether the Edition Manager is available on the system by using the Gestalt function with the gestaltEditionMgrAttr ('edtn') selector. If the response parameter returns 1 in the bit defined by the gestaltEditionMgrPresent constant (bit 0), the Edition Manager is present.
  1259. If the Edition Manager is present, load it into memory using the InitEditionPack function. This function determines whether the machine has enough space in the system heap for the Edition Manager to operate.
  1260. err := InitEditionPack;
  1261. If the InitEditionPack function returns noErr, you have enough space to load the package. If you do not have enough space, the application can either terminate itself or continue with the Edition Manager functionality disabled.
  1262.  
  1263.  
  1264. Receiving Apple Events From the Edition Manager
  1265.  
  1266. Applications that use the Edition Manager must support Apple events. This requires that your application support the required Open Documents event and Apple events sent by the Edition Manager. See the chapter “Introduction to Apple Events” in this book for general information on Apple events.
  1267. Apple events sent by the Edition Manager arrive as high-level events. The EventRecord data type defines the event record.
  1268. TYPE EventRecord =
  1269.     RECORD
  1270.         what:                Integer;                {kHighLevelEvent}
  1271.         message:                LongInt;                {'sect'}
  1272.         when:                LongInt;
  1273.         where:                Point;                {'read', 'writ', 'cncl', 'scrl'}
  1274.         modifiers:                Integer;
  1275.     END;
  1276. The Edition Manager can send these Apple events with the event class and event ID as shown here:
  1277. n    Section Read events ('sect' 'read')
  1278. n    Section Write events ('sect' 'writ')
  1279. n    Section Cancel events ('sect' 'cncl')
  1280. n    Section Scroll events ('sect' 'scrl')
  1281. Each time your application creates a publisher or a subscriber, the Edition Manager registers its section. When an edition is updated, the Edition Manager scans its list to locate registered subscribers. For each registered subscriber that is set up to receive updated editions automatically, your application receives a Section Read event.
  1282. If the Edition Manager discovers that an edition file is missing while registering a publisher, it creates a new edition file and sends the publisher a Section Write event. 
  1283. When you receive a Section Cancel event, you need to cancel the specified section. Note that the current Edition Manager does not send you Section Cancel events, but you do need to provide a handler for future expansion.
  1284. If the user selects a subscriber within a document and then selects Open Publisher in the subscriber options dialog box, the publishing application receives the Open Documents event and opens the document containing the publisher. The publishing application also receives a Section Scroll event. Scroll to the location of the publisher, display this section on the user’s screen, and turn on its border.
  1285. See “Opening and Closing a Document Containing Sections” beginning on page 2-22 for detailed information on registering and unregistering a section and writing data to an edition. See “Using Publisher and Subscriber Options” beginning on page 2-43 for information on publisher and subscriber options.
  1286. After receiving an Apple event sent by the Edition Manager, use the Apple Event Manager to extract the section handle. In addition, you must also call the IsRegisteredSection function to determine whether the section is registered. It is possible (because of a race condition) to receive an event for a section that you recently disposed of or unregistered. One way to ensure that an event corresponds to a valid section is to call the IsRegisteredSection function after you receive an event.  
  1287. err := IsRegisteredSection (sectionH);
  1288. Listing 2-1 illustrates how to use the Apple Event Manager and install an event handler to handle Section Read events. You can write similar code for Section Write events, Section Scroll events, and Section Cancel events.
  1289.  
  1290. Listing 2-1    Accepting Section Read events and verifying if a section is registered
  1291.  
  1292. {the following goes in your initialization code}
  1293. myErr := AEInstallEventHandler(sectionEventMsgClass {'sect'},
  1294.                                          sectionReadMsgID {'read'},
  1295.                                          @MyHandleSectionReadEvent, 0,
  1296.                                          FALSE);
  1297.  
  1298. {this is the routine the Apple Event Manager calls when a }
  1299. { Section Read event arrives}
  1300.  
  1301. FUNCTION MyHandleSectionReadEvent(theAppleEvent,
  1302.                                              reply: AppleEvent;
  1303.                                              refCon: LongInt): OSErr;
  1304. VAR
  1305.     myErr:                OSErr;
  1306.     sectionH:                SectionHandle;
  1307. BEGIN
  1308.     {get section handle out of Apple event message buffer}
  1309.     myErr := MyGetSectionHandleFromEvent(theAppleEvent, sectionH);
  1310.     IF myErr = noErr THEN
  1311.     BEGIN
  1312.         IF IsRegisteredSection(sectionH) = noErr THEN
  1313.             {if section is registered, read the new data}
  1314.             MyHandleSectionReadEvent := DoSectionRead(sectionH);
  1315.     END 
  1316.     ELSE
  1317.         MyHandleSectionReadEvent := myErr;
  1318. END; {MyHandleSectionReadEvent}
  1319.  
  1320.  
  1321. {this routine reads in subscriber data and updates its display}
  1322. FUNCTION DoSectionRead(subscriber: SectionHandle): OSErr;
  1323. BEGIN
  1324.     {your code here}
  1325. END;        {DoSectionRead}
  1326. {this is part of your Apple event–handling code}
  1327. FUNCTION MyGetSectionHandleFromEvent(theAppleEvent: AppleEvent;
  1328.                                                  VAR sectionH: SectionHandle)
  1329.                                                  : OSErr;
  1330. VAR
  1331.     ignoreType:                    DescType;
  1332.     ignoreSize:                    Size;
  1333. BEGIN
  1334.     {parse section handle out of message buffer}
  1335.     MyGetSectionHandleFromEvent
  1336.         := AEGetParamPtr( theAppleEvent,                                                {event to parse}
  1337.                                 keyDirectObject,                        {look for direct }
  1338.                                                         { object}
  1339.                                 typeSectionH,                         {want a SectionHandle}
  1340.                                 ignoreType,                        {ignore type it could }
  1341.                                                         { get}
  1342.                                 @sectionH,                         {put SectionHandle }
  1343.                                                         { here}
  1344.                                 SizeOf(sectionH),                        {size of storage for }
  1345.                                                         { SectionHandle}
  1346.                                 ignoreSize);                        {ignore storage it }
  1347.                                                         { used}
  1348. END; {MyGetSectionHandleFromEvent} 
  1349. In addition to the Section Read, Section Write, Section Cancel, and Section Scroll events, your application can also respond to the Create Publisher event. For more information on this event, as well as additional information on how to handle Apple events, see the chapter “Responding to Apple Events” in this book. 
  1350.  
  1351. Creating the Section Record and Alias Record
  1352.  
  1353. Your application is responsible for creating a section record and an alias record for each publisher and subscriber section within an open document.
  1354. The section record identifies each section as a publisher or subscriber and provides identification for each section. The section record does not contain the data within the section; it describes the attributes of the section. Your application must provide its own method for associating the data within a section with its section record. Your application is also responsible for saving the data in the section.
  1355. The alias field of the section record contains a handle to its alias record. The alias record is a reference to the edition container from the document that contains the publisher or subscriber section. You should be familiar with the Alias Manager’s conventions for creating alias records and identifying files, folders, and volumes to locate files that have been moved, copied, or restored from backup. For information on the Alias Manager, see Inside Macintosh: Files.
  1356. When a user saves a document, your application should store all section records and alias records in the document’s resource fork. Corresponding section records and alias records should have the same resource ID.
  1357. Figure 2-9 shows a document containing a publisher and subscriber, and the corresponding section records and alias records.
  1358.  
  1359. Figure 2-9    A document with a publisher and subscriber and its resource fork
  1360.  
  1361. A section record contains information to identify the data contained within a section as a publisher or a subscriber, a time stamp to record the last modification of the section, and unique identification for each section. The SectionRecord data type defines the section record.
  1362. TYPE SectionRecord = 
  1363.     RECORD
  1364.         version:                    SignedByte;                    {always 1 in 7.0}
  1365.         kind:                    SectionType;                    {publisher or subscriber}
  1366.         mode:                    UpdateMode;                    {automatic or manual}
  1367.         mdDate:                    TimeStamp;                    {last change in document}
  1368.         sectionID:                    LongInt;                    {application-specific, }
  1369.                                                 { unique per document}
  1370.         refCon:                    LongInt;                    {application-specific}
  1371.         alias:                    AliasHandle;                    {handle to alias record}
  1372.  
  1373.         {The following fields are private and are set up by the }
  1374.         { RegisterSection function described later within this }
  1375.         { chapter. Do not modify the private fields.}
  1376.  
  1377.         subPart:                    LongInt;                    {private}
  1378.         nextSection:                    SectionHandle;                    {private, do not use as a }
  1379.                                                 { linked list}
  1380.         controlBlock:                    Handle;                    {may be used for comparison }
  1381.                                                 { only}
  1382.         refNum:                    EditionRefNum;                    {private}
  1383. END;
  1384. Field descriptions
  1385. version    Indicates the version of the section record, currently $01.
  1386.  
  1387. kind    Defines the section type as either publisher or subscriber with the stPublisher or stSubscriber constant.
  1388. mode    Indicates if editions are updated automatically or manually.
  1389. mdDate    Indicates which version (modification date) of the section’s contents is contained within the publisher or subscriber. The mdDate field is set to 0 when you create a new subscriber section and to the current time when you create a new publisher. Be sure to update this field each time publisher data is modified. The section’s modification date is compared to the edition’s modification date to determine whether the section and the edition contain the same data. The section modification date is displayed in the publisher and subscriber options dialog boxes. See “Closing an Edition” on page 2-28 for detailed information.
  1390. sectionID    Provides a unique number for each section within a document. A simple way to implement this is to create a counter for each document that is saved to disk with the document. The counter should start at 1. The section ID is currently used as a tie breaker in the GoToPublisherSection function when there are multiple publishers to the same edition in a single document. The section ID should not be 0 or –1. See “Duplicating Publishers and Subscribers” on page 2-58 for information on multiple publishers.
  1391. refCon    Reference constant available for application-specific use.
  1392. alias    Contains a handle to the alias record for a particular section within a document.
  1393. Whenever the user creates a publisher or subscriber, call the NewSection function to create the section record and the alias record.
  1394. err := NewSection(container, sectionDocument, kind, sectionID,
  1395.                        initialMode, sectionH);
  1396. The NewSection function creates a new section record (either publisher or subscriber), indicates whether editions are updated automatically or manually, sets the modification date, and creates an alias record from the document containing the section to the edition container.
  1397. You can set the sectionDocument parameter to NIL if the current document has never been saved. Use the AssociateSection function to update the alias record of a registered section when the user names or renames a document by choosing Save As from the File menu. If you are creating a subscriber with the initialMode parameter set to receive new editions automatically, your application receives a Section Read event each time a new edition becomes available for this subscriber.
  1398. If an error is encountered, the NewSection function returns NIL in the sectionH parameter. Otherwise, NewSection returns a handle to the allocated section record in the sectionH parameter.
  1399. Set the initialMode parameter to the update mode for each subscriber and publisher created. You can specify the update mode using these constants:
  1400. CONST            sumAutomatic                    = 0;            {subscriber receives new }
  1401.                                             { editions automatically}
  1402.             sumManual                    = 1;            {subscriber receives new }
  1403.                                             { editions manually}
  1404.             pumOnSave                    = 0;            {publisher sends new }
  1405.                                             { editions on save}
  1406.             pumManual                    = 1;            {publisher does not send }
  1407.                                             { new editions until user }
  1408.                                              { request}
  1409. See “Using Publisher and Subscriber Options” beginning on page 2-43 for detailed information on update modes for publishers and subscribers. See Listing 2-4 beginning on page 2-33 for code that uses the NewSection function to create a publisher. See Listing 2-6 on page 2-40 for code that uses NewSection to create a subscriber. 
  1410.  
  1411. Saving a Document Containing Sections
  1412.  
  1413. When saving a document that contains sections, you should write out each section record as a resource of type 'sect' and write out each alias record as a resource of type 'alis' with the same ID as the section record. See the chapter “Resource Manager” in Inside Macintosh: More Macintosh Toolbox for detailed information on resources. 
  1414. If a user closes a document that contains newly created publishers without attempting to save its contents, you should display an alert box similar to the one shown in Figure 2-10.
  1415.  
  1416. Figure 2-10    The new publisher alert box
  1417.  
  1418. If you keep the section records and alias records for each publisher and subscriber as resources, you can use the ChangedResource or WriteResource function. If you detach the section records and alias records from each section, you need to clone the handles and use the AddResource function. See the chapter “Resource Manager” in Inside Macintosh: More Macintosh Toolbox for detailed information on the ChangedResource, WriteResource, and AddResource functions.
  1419. Use the PBExchangeFiles function to ensure that the file ID remains the same each time you save a document that contains sections. Saving a file typically involves creating a new file (with a temporary name), writing data to it, closing it, and then deleting the original file that you are replacing. You rename the temporary file with the original filename, which leads to a new file ID. The PBExchangeFiles function swaps the contents of the two files (even if they are open) by getting both catalog entries and swapping the allocation pointers. If the files are open, the file control block (FCB) is updated so that the reference numbers still access the same contents (under a new name). See Inside Macintosh: Files for detailed information on the PBExchangeFiles function.
  1420. Listing 2-2 illustrates how to save a file that contains sections. If the contents of a publisher have changed since the last save, the application-defined procedure MySaveDocument writes the publisher’s data to its edition. It then writes out to the saved document the section records and alias records of all publishers and subscribers. MySaveDocument calls another application-defined routine, MyGetSectionAliasPair, to return a handle and resource ID to a section. As described earlier, you should write out the eligible section records and alias records as resources to allow for future compatibility. There are several different techniques for saving or adding resources; this listing illustrates one technique. The section handles are still valid after using the AddResource function because this listing illustrates just saving, not closing, the file.
  1421. Before you write out sections, you need to see if any publisher sections share the same control block. Publishers that share the same control block share the same edition.
  1422. If a user creates an identical copy of a file by choosing Save As from the File menu and does not make any changes to this new file, you simply use the AssociateSection function to indicate to the Edition Manager which document a section is located in.
  1423.  
  1424. Listing 2-2    
  1425. Saving a document containing sections
  1426.  
  1427. PROCEDURE MySaveDocument(thisDocument: MyDocumentInfoPtr;
  1428.                                    numberOfSections: Integer);
  1429. VAR
  1430.     aSectionH:                        SectionHandle;
  1431.     copiedSectionH:                        Handle;
  1432.     copiedAliasH:                        Handle;
  1433.     resID:                        Integer;
  1434.     thisone:                        Integer;
  1435.     myErr:                        OSErr;
  1436. BEGIN
  1437.     FOR thisone := 1 TO numberOfSections DO
  1438.     BEGIN
  1439.         aSectionH := MyGetSectionAliasPair(thisDocument, thisone, 
  1440.                                                       resID);
  1441.         IF (aSectionH^^.kind = stPublisher) &
  1442.             (aSectionH^^.mode = pumOnSave) &
  1443.             (MyCheckForDataChanged(aSectionH)) THEN
  1444.             DoWriteEdition(aSectionH);
  1445.     END; {end of for}
  1446.     {set the curResFile to the resource fork of thisDocument}
  1447.     UseResFile(thisDocument^.resForkRefNum);
  1448.     {write all section and alias records to the document}
  1449.     FOR thisone := 1 TO numberOfSections DO
  1450.     BEGIN
  1451.         {given an index, get the next section handle and resID }
  1452.         { from your internal list of sections for this file}
  1453.         aSectionH := MyGetSectionAliasPair(thisDocument, thisone, 
  1454.                                                       resID);
  1455.         {check for duplication of control block values}
  1456.         MyCheckForDupes(thisDocument, numberOfSections);
  1457.         {save section record to disk}
  1458.         copiedSectionH := Handle(aSectionH);
  1459.         myErr := HandToHand(copiedSectionH);
  1460.         AddResource(copiedSectionH, rSectionType, resID, '');
  1461.         {save alias record to disk}
  1462.         copiedAliasH := Handle(aSectionH^^.alias);
  1463.         myErr := HandToHand(copiedAliasH);
  1464.         AddResource(copiedSectionH, rAliasType, resID, '');
  1465.     END; {end of for}
  1466.     {write rest of document to disk}
  1467. END; 
  1468.  
  1469.  
  1470. Opening and Closing a Document Containing Sections
  1471.  
  1472. When opening a document that contains sections, your application should use the GetResource function to get the section record and the alias record for each publisher and subscriber. Set the alias field of the section record to be the handle to the alias. See the chapter “Resource Manager” in Inside Macintosh: More Macintosh Toolbox for detailed information on the GetResource function.
  1473. You also need to register each section using the RegisterSection function. The RegisterSection function informs the Edition Manager that a section exists.
  1474. err := RegisterSection(sectionDocument, sectionH,
  1475.                               aliasWasUpdated);
  1476. The RegisterSection function adds the section record to the Edition Manager’s list of registered sections. This function assumes that the alias field of each section record is a handle to the alias record. The alias record is a reference to the edition container from the section’s document. If the RegisterSection function successfully locates the edition container for a particular section, the section is registered through a shared control block. The control block is a private field in the section record.
  1477. If the RegisterSection function cannot find the edition container for a particular subscriber, RegisterSection returns the containerNotFoundWrn result code. If the RegisterSection function cannot find the edition container for a particular publisher, RegisterSection creates an empty edition container for the publisher in the last place the edition was located. The Edition Manager sends your application a Section Write event for that section. 
  1478. When a user attempts to open a document that contains multiple publishers to the same edition, you should warn the user by displaying an alert box (see “Duplicating Publishers and Subscribers” on page 2-58).
  1479. When a user opens a document that contains a subscriber (with an update mode set to automatic), receives a new edition, and then closes the document without making any changes to the file, you should update the document and simply allow the user to close it. You do not need to prompt the user to save changes to the file.
  1480. When closing a document that contains sections, you must unregister each section (using the UnRegisterSection function) and dispose of each corresponding section record and alias record.
  1481. err := UnRegisterSection(sectionH);
  1482. The UnRegisterSection function removes the section record from the list of registered sections and unlinks itself from the shared control block.
  1483. Listing 2-3 illustrates how to open an existing file that contains sections. As described earlier, you should retrieve the section and alias resources, connect the pair through the alias field of the section record, and register the section with the Edition Manager. There are many different techniques for retrieving resources; this listing shows one technique. If an alias was out of date and was updated by the Alias Manager during the resolve, the Edition Manager sets the aliasWasUpdated parameter of the RegisterSection function to TRUE. This means that you should save the document. Additionally, your application must maintain its own list of registered sections for each open document that contains sections. You use this list to write out new editions for updated publishers within a document.
  1484.  
  1485. Listing 2-3    Opening a document containing sections
  1486.  
  1487. PROCEDURE MyOpenExistingDocument(thisDocument: MyDocumentInfoPtr);
  1488. VAR
  1489.     sectionH:                            SectionHandle;
  1490.     aliasH:                            AliasHandle;
  1491.     aliasWasUpdated:                            Boolean;
  1492.     registerErr:                            OSErr;
  1493.     resID:                            Integer;
  1494.     theResType:                            ResType;
  1495.     thisone:                            Integer;
  1496.     numberOfSections:                            Integer;
  1497.     aName:                            Str255;
  1498. BEGIN
  1499.     UseResFile(thisDocument^.resForkRefNum);
  1500.     {find out the number of section resources}
  1501.     numberOfSections := Count1Resources(rSectionType);
  1502.     FOR thisone := 1 TO numberOfSections DO
  1503.     BEGIN
  1504.         sectionH := SectionHandle(Get1IndResource(rSectionType,
  1505.                                                                 thisone));
  1506.         IF sectionH = NIL THEN                                {something could be wrong with }
  1507.             MySectionErr;                            { the file, handle appropriately} 
  1508.         {get resource ID of the section & use same ID for alias}
  1509.         GetResInfo(Handle(sectionH), resID, theResType, aName);
  1510.         {detaching is not necessary, but it is convenient}
  1511.         DetachResource(Handle(sectionH));
  1512.         {get the alias}
  1513.         aliasH := AliasHandle(Get1Resource(rAliasType, resID));
  1514.         IF aliasH = NIL THEN                                {something could be wrong with }
  1515.             MyAliasErr;                            { the file, handle appropriately} 
  1516.         DetachResource(Handle(aliasH));
  1517.  
  1518.         {connect section and alias together}
  1519.         sectionH^^.alias := aliasH;
  1520.         {register the section}
  1521.         registerErr := RegisterSection(thisDocument^.fileSpec,
  1522.                                                        sectionH, aliasWasUpdated);
  1523.         {The RegisterSection function may return an error if }
  1524.         { a section is not registered. This is not a fatal error. }
  1525.         { Continue looping to register remaining sections.}
  1526.         {add this section/alias pair to your internal bookkeeping}
  1527.         MyAddSectionAliasPair(thisDocument, sectionH, resID);
  1528.         IF aliasWasUpdated THEN 
  1529.             {If alias has changed, make a note of this. }
  1530.             { It's important to know this when you save.}
  1531.             MyAliasHasChanged(sectionH);
  1532.     END; {end of FOR}
  1533. END;  
  1534.  
  1535. Reading and Writing a Section
  1536.  
  1537. Your application writes publisher data to an edition. New publisher data replaces the previous contents of the edition, making the previous edition information irretrievable. Your application reads data from an edition for each subscriber within a document.
  1538. The following sections describe how to
  1539. n    use different formats to write to or read from an edition
  1540. n    open an edition to initiate writing or reading
  1541. n    set a format mark
  1542. n    write to or read from an edition
  1543. n    close an edition after successfully writing or reading data
  1544.  
  1545. Formats in an Edition
  1546.  
  1547. You can write data to an edition in several different formats. These formats are the same as scrap format types. Scrap format types are indicated by a four-character tag.
  1548. Typically, when a user copies data, you identify the scrap format types and then write the data to the scrap. With the Edition Manager, when a user decides to publish data, you identify the format types and then write the data to an edition. You can write multiple formats of the same data.
  1549. For an edition, you should write your preferred formats first. In general, to write data to an edition, your application should use either 'TEXT' format or 'PICT' format. This allows your application to share data with most other applications. To subscribe to an edition, your application should be able to read both 'TEXT' and 'PICT' files. In addition, your application can write any other private formats that you want to support.
  1550. Scrap format types are described in the chapter “Scrap Manager” in Inside Macintosh: More Macintosh Toolbox.
  1551. A few special formats are defined as constants.
  1552. CONST        kPublisherDocAliasFormat                                    = 'alis';    {alias record from the }
  1553.                                                         { edition to publisher}
  1554.         kPreviewFormat                                    = 'prvw';    {'PICT' thumbnail }
  1555.                                                         { sketch}
  1556.         kFormatListFormat                                    = 'fmts';    {lists all available }
  1557.                                                         { formats}
  1558. The kPublisherDocAliasFormat ('alis') format is written by the Edition Manager. It is an alias record from the edition to the publisher’s document. Appended to the end of the alias is the section ID of the publisher, which the Edition Manager uses to distinguish between multiple publishers to a single edition. You should discourage users from making multiple copies of the same publisher. See “Duplicating Publishers and Subscribers” on page 2-58 for detailed information.
  1559. In addition to writing a publisher’s data to an edition in the 'TEXT' format or 'PICT' format, your application can also write data to an edition in the kPreviewFormat ('prvw') format. If you provide a 'prvw' format in an edition, the Edition Manager uses it to display a preview of the edition data in the preview area of the subscriber dialog box. The 'prvw' format has the same format as a 'PICT' file. To draw a preview in the 'prvw' format, the Edition Manager calls DrawPicture with a rectangle of 120 by 120 pixels. (See Inside Macintosh: Imaging for more information about DrawPicture.) Your application should provide data in a 'prvw' format so that the data displays well in a rectangle of this size. Your application can also use this preview to display subscriber data within a document (to save space).
  1560. If your application does not provide a preview in the 'prvw' format for an edition, the Edition Manager attempts to provide a preview by using the edition’s 'PICT' format. To draw a preview in the 'PICT' format, the Edition Manager examines the picture’s bounding rectangle and calls DrawPicture with a rectangle that scales the picture proportionally and centers it in a 120-by-12-pixel area. 
  1561. The kFormatListFormat ('fmts') format is a virtual format that is read but never written. It is a list of all the formats and their lengths. Applications can use this format in place of the EditionHasFormat function (described in “Choosing Which Edition Format to Read” on page 2-41), which provides a procedural interface to determine which formats are available.
  1562. If your application can read two or more of the available formats, use 'fmts' to determine the priority of these formats for a particular edition. The order of 'fmts' reflects the order in which the formats were written.
  1563. The FormatsAvailable data type defines a record for the 'fmts' format.
  1564. TYPE FormatsAvailable = ARRAY[0..0] OF
  1565.     RECORD
  1566.         theType:                FormatType;                    {format type for an edition}
  1567.         theLength:                LongInt;                    {length of edition format }
  1568.                                             { type}
  1569.     END;
  1570. For example, an edition container may have a format type 'TEXT' of length 100, and a format type 'styl' of length 32. A subscriber to this edition can open it and then read the format type 'fmts' to list all available formats. In this example, it returns 16 bytes: 'TEXT' $00000064 'styl' $00000020.
  1571.  
  1572. Opening an Edition
  1573.  
  1574. For a publisher, use the OpenNewEdition function to initiate the writing of data to an edition. (Note that the edition container must already exist before you initiate writing; see “Creating the Edition Container” beginning on page 2-32.)
  1575. err := OpenNewEdition(publisherSectionH, fdCreator,
  1576.                              publisherSectionDocument, refNum);
  1577. The publisherSectionH parameter is the publisher section that you are writing to the edition. The fdCreator parameter is the Finder creator type of the new edition. (The edition container file already has a creator type; you can specify the same creator type or establish a new creator type for the edition.)
  1578. The publisherSectionDocument parameter specifies the document that contains the publisher. This parameter is used to create an alias from the edition to the publisher’s document. If you pass NIL for publisherSectionDocument, an alias is not made in the edition file. The refNum parameter returns the reference number for the edition.
  1579. For a subscriber, use the OpenEdition function to initiate the reading of data from 
  1580. an edition.
  1581. err := OpenEdition(subscriberSectionH, refNum);
  1582. The subscriberSectionH parameter is a handle to the section record for a given section. The refNum parameter returns the reference number for the edition.
  1583. The user may rename or move the edition in the Finder. Before writing to or reading data from an edition, the Edition Manager verifies the name of the edition. This process is referred to as synching or synchronization. Synching ensures that the Edition Manager’s existing edition names correspond to the Finder’s existing edition names by updating the control block.
  1584.  
  1585.  
  1586. Format Marks
  1587.  
  1588. Each format has its own mark. The mark indicates the next position of a read or write operation. Initially, a mark automatically defaults to 0. After reading or writing data, the format mark is set past the last position written to or read from. The mark is similar to the File Manager’s current read or write position marker for a data fork. Any time that an edition is open (after calling the OpenEdition or the OpenNewEdition function), any of the marks for each format can be queried or set. 
  1589. To set the current mark for a section format to a new location, use the SetEditionFormatMark function.
  1590. err := SetEditionFormatMark(whichEdition, whichFormat,
  1591.                                      setMarkTo);
  1592. To get the current mark for a format in an edition file, use the GetEditionFormatMark function.
  1593. err := GetEditionFormatMark(whichEdition, whichFormat,
  1594.                                      currentMark);
  1595.  
  1596. Reading and Writing Edition Data
  1597.  
  1598. The Edition Manager allows you to read or write data a few bytes at a time (as with a data fork of a Macintosh file) instead of in one block (as with the Scrap Manager). You can read sequentially by setting the mark to 0 and repeatedly calling read, or you can jump to a specific offset by setting the mark there. The Edition Manager also adds the capability to stream multiple formats by keeping a separate mark for each format. This allows you to write a few bytes of one format and then write a few bytes of another format, and so forth.
  1599. Once you have opened the edition container for a particular publisher, you can begin writing data to the edition. Use the WriteEdition function to write publisher data to an edition.
  1600. err := WriteEdition(whichEdition, whichFormat, buffPtr, buffLen);
  1601. The WriteEdition function writes the specified format (beginning at the current mark for that format type) from the buffer pointed to by the buffPtr parameter up to buffLen bytes. 
  1602. After you open the edition container for a subscriber and determine which formats to read, use the ReadEdition function to read edition data.
  1603. err := ReadEdition(whichEdition, whichFormat, buffPtr, buffLen);
  1604. The ReadEdition function reads the data with the specified format (whichFormat) from the edition into the buffer. The ReadEdition function begins reading at the current mark for that format and continues to read up to buffLen bytes. The actual number of bytes read is returned in the buffLen parameter. Once the buffLen parameter returns a value smaller than the value you have specified, there is no additional data to read, and the ReadEdition function returns a noErr result code. 
  1605. Note
  1606. The Translation Manager (if it is available) attempts implicit translation under certain circumstances. For instance, it does so when your application attempts to read from an edition a format type that is not in the edition. In this case, the Translation Manager attempts to translate the data into the requested format. For more information, see the chapter “Translation Manager” in Inside Macintosh: More Macintosh Toolbox.u
  1607.  
  1608.  
  1609. Closing an Edition
  1610.  
  1611. When you are done writing to or reading data from an edition, call the CloseEdition function.
  1612. err := CloseEdition(whichEdition, successful);
  1613. Each time a user edits a publisher within a document, you must update the modification date in the section record (even if the data is not yet written). When the update mode is set to Manually, the user can compare the modification dates for a publisher and its edition in the publisher options dialog box. One modification date indicates when the publisher last wrote data to the edition, and the other modification date indicates when the publisher section was last edited.
  1614. If the successful parameter for a publisher is TRUE, the CloseEdition function makes the newly written data available to subscribers and sets the modification date in the mdDate field of the edition to correspond to the modification date of the publisher’s section record. If the two dates differ, the Edition Manager sends a Section Read event to all current subscribers.
  1615. If the successful parameter for a subscriber is TRUE, the CloseEdition function sets the modification date of the subscriber’s section record to correspond to the modification date of the edition.
  1616. If you cannot successfully read from or write data to an edition, set the successful parameter to FALSE. For a publisher, data is not written to the edition, but it should still be saved with the document that contains the section. When the document is next saved, data can then be written to the edition. See “Closing an Edition After Reading or Writing” on page 2-88 for additional information on the CloseEdition function.
  1617.  
  1618.  
  1619. Creating a Publisher
  1620.  
  1621. You need to support a Create Publisher menu command in the Edit menu. When a user selects a portion of a document and chooses Create Publisher from this menu, you should display the publisher dialog box on the user’s screen. The Create Publisher menu command should remain dimmed until the user selects a portion of a document.
  1622. Use the NewPublisherDialog function to display the publisher dialog box on the user’s screen. This function is similar to the CustomPutFile procedure described in the chapter “Standard File Package” in Inside Macintosh: Files.
  1623. err := NewPublisherDialog(reply);
  1624. The dialog box contains space for a preview (a thumbnail sketch) of the edition and a space for the user to type the name of the edition in which to write the publisher data. Figure 2-11 illustrates a sample publisher dialog box.
  1625.  
  1626. Figure 2-11    A sample publisher dialog box
  1627.  
  1628. The NewPublisherDialog function displays the preview (provided by your application), displays a text box with the default name of the edition (provided by your application), and handles all user input until the user clicks 
  1629. Publish or Cancel.
  1630. You pass a new publisher reply record as a parameter to the NewPublisherDialog function.
  1631. TYPE NewPublisherReply = 
  1632.     RECORD
  1633.         canceled:                Boolean;                        {user clicked Cancel}
  1634.         replacing:                Boolean;                        {user chose existing }
  1635.                                                 { filename for an edition}
  1636.         usePart:                Boolean;                        {always FALSE in version 7.0}
  1637.         preview:                Handle;                        {handle to 'prvw', 'PICT', }
  1638.                                                 { 'TEXT', or 'snd ' data}
  1639.         previewFormat:                                        {type of preview}
  1640.                         FormatType;                    
  1641.         container:                EditionContainerSpec;                            {initially, default name }
  1642.                                                 { and location of edition; }
  1643.                                                 { on return, edition name & }
  1644.                                                 { location chosen by the } 
  1645.                                                 { user to publish data to}
  1646.     END;
  1647. You fill in the usePart, preview, previewFormat, and container fields of the new publisher reply record.
  1648. Always set the usePart field to FALSE. The preview field should contain either NIL or the data to display in the preview. The previewFormat field should contain 'PICT', 'TEXT', 'snd ', or 'prvw'.
  1649. Set the container field to be the default name and folder for the edition. The default name should reflect the data contained in the publisher. For example, if a user publishes a bar chart of sales information entitled “sales data,” then the default name for the edition could also be “sales data.” Otherwise, you should use the document name followed by a hyphen (-) and a number to establish uniqueness. For example, your default name could be “January Totals - 3.”
  1650. If the document has not been saved, the default name should be “untitled edition <n>” where n is a number to establish uniqueness. The default folder should be the same as the edition for the last publisher created in the same document. If this is the first publisher in the document, the default folder should be the same folder that the document is in.
  1651. The canceled field of the new publisher reply record indicates whether the user clicked Cancel. The replacing field indicates whether the user chose to replace an existing edition file. If replacing returns FALSE, call the CreateEditionContainerFile function to create an edition file.
  1652. The container field is of data type EditionContainerSpec.
  1653. TYPE EditionContainerSpec = 
  1654.     RECORD
  1655.         theFile:                    FSSpec;                {record that identifies the }
  1656.                                             { file to contain edition data}
  1657.         theFileScript:                    ScriptCode;                {script code of filename}
  1658.         thePart:                    LongInt;                {which part of file, }
  1659.                                             { always kPartsNotUsed}
  1660.         thePartName:                    Str31;                {not used in version 7.0}
  1661.         thePartScript:                    ScriptCode;                {not used in version 7.0}
  1662.     END;
  1663. The field theFile is a file system specification record, a data structure of type FSSpec. You identify the edition using a volume reference number, directory ID, and filename. When specifying an edition, follow the standard conventions described in Inside Macintosh: Files.
  1664. After filling in the fields of the new publisher reply record, pass it as a parameter to the NewPublisherDialog function, which displays the publisher dialog box.
  1665. err := NewPublisherDialog(reply);
  1666. After displaying the publisher dialog box, use the CreateEditionContainerFile function to create the edition container, and then use the NewSection function to create the section record and the alias record. See the next section, “Creating the Edition Container,” and “Creating the Section Record and Alias Record” on page 2-15 for detailed information.
  1667. The following code segment illustrates how your application might respond to the user choosing the Create Publisher menu item. In this case, the code sets up the preview for the edition, sets the default name for the edition container, and calls an application-defined function (DoNewPublisher, shown in Listing 2-4 on page 2-33) to display the publisher dialog box on the user’s screen. An application might call the DoNewPublisher function in response to the user’s choosing Create Publisher from the Edit menu or in response to handling the Create Publisher event. The chapter “Responding to Apple Events” in this book gives an example of a handler for the Create Publisher event.
  1668. VAR
  1669.     thisDocument:                             MyDocumentInfoPtr; 
  1670.     promptForDialog:                             Boolean;
  1671.     preview:                             Handle; 
  1672.     previewFormat:                             FormatType; 
  1673.     defaultLocation:                             EditionContainerSpec;
  1674.     myErr:                            OSErr;
  1675.  
  1676.  
  1677. BEGIN
  1678.     {Get a preview to show the user. The MyGetPreviewForSelection }
  1679.     { function returns a handle to the preview.}
  1680.     preview := MyGetPreviewForSelection(thisDocument);
  1681.     previewFormat := 'TEXT';
  1682.     defaultLocation := MyGetDefaultEditionSpec(thisDocument);
  1683.     promptForDialog := TRUE;
  1684.     myErr := DoNewPublisher(thisDocument, promptForDialog, preview, 
  1685.                                     previewFormat, defaultLocation);
  1686. END;
  1687.  
  1688. Creating the Edition Container
  1689.  
  1690. Use the CreateEditionContainerFile function to create an edition container to hold the publisher data.
  1691. err := CreateEditionContainerFile(editionFile, fdCreator,
  1692.                                              editionFileNameScript);
  1693. This function creates an edition container. The edition container is empty (that is, it does not contain any formats) at this time.
  1694. To associate an icon with the edition container, create the appropriate entries for the icon in your application’s bundle. See the chapter “Finder Interface” in Inside Macintosh: Macintosh Toolbox Essentials for additional information. Depending on the contents of the edition, the file type will be 'edtp' (for graphics), 'edtt' (for text), or 'edts' (for sound).
  1695. After creating the edition container, use the NewSection function to create the section record and alias record for the section.
  1696. Listing 2-4 illustrates how to create a publisher. The DoNewPublisher function shown in the listing is a function provided by an application. Note that an application might call the DoNewPublisher function in response to the user’s choosing the Create Publisher command or in response to the Create Publisher event. The chapter “Responding to Apple Events” in this book gives an example of a handler for the Create Publisher event.
  1697. The parameters to the DoNewPublisher function include a pointer to information about the document, a Boolean value that indicates if the function should display the new publisher dialog box, the preview for the edition, the preview format, and an edition container.
  1698. The function displays the publisher dialog box if requested, letting the user accept or change the name of the edition and the location where the edition should reside. Use the CreateEditionContainerFile function to create the edition with the given name and location. Use the NewSection function to create a new section for the publisher.
  1699. After the section is created, you must write out the edition data. Be sure to add the newly created section to your list of sections for this document. There are several different techniques for creating publishers and unique IDs; this listing displays one technique.
  1700. After creating the edition container and creating a new section record, the DoNewPublisher function calls another application-defined routine, DoWriteEdition, to open the edition and write data to it.
  1701.  
  1702. Listing 2-4    Creating a publisher
  1703.  
  1704. FUNCTION DoNewPublisher(thisDocument: MyDocumentInfoPtr;
  1705.                                 promptForDialog: Boolean; 
  1706.                                 preview: Handle;
  1707.                                 previewFormat: FormatType;
  1708.                                 editionSpec: EditionContainerSpec)
  1709.                                 : OSErr;
  1710. VAR
  1711.     getLastErr, dialogErr:                                OSErr;
  1712.     createErr, sectionErr:                                OSErr;
  1713.     resID:                                Integer;
  1714.     thisSectionH:                                SectionHandle;
  1715.     reply:                                NewPublisherReply;
  1716. BEGIN
  1717.     {set up info for new publisher reply record}
  1718.     reply.replacing := FALSE;
  1719.     reply.usePart := FALSE;
  1720.     reply.preview := preview;
  1721.     reply.previewFormat := previewFormat;
  1722.     reply.container := editionSpec;
  1723.     IF promptForDialog THEN 
  1724.     BEGIN        {user interaction is allowed}
  1725.         {display dialog box and let user select}
  1726.         dialogErr := NewPublisherDialog(reply);
  1727.         {dispose of preview data handle}
  1728.         DisposeHandle(reply.preview);
  1729.         IF dialogErr <> noErr THEN MyErrHandler(dialogErr);
  1730.         IF reply.canceled THEN
  1731.         BEGIN            {do nothing if user canceled}
  1732.             DoNewPublisher := userCanceledErr;
  1733.             EXIT(DoNewPublisher);
  1734.         END;
  1735.     END;        {of promptForDialog}
  1736.  
  1737.  
  1738.     IF NOT reply.replacing THEN
  1739.     BEGIN        
  1740.         {if user isn't replacing an existing file, create a new one}
  1741.         createErr := 
  1742.             CreateEditionContainerFile(reply.container.theFile,
  1743.                                               kAppSignature,
  1744.                                               reply.container.theFileScript);
  1745.         IF createErr <> noErr THEN
  1746.         BEGIN
  1747.             DoNewPublisher := errAEPermissionDenied;
  1748.             EXIT(DoNewPublisher);
  1749.         END;
  1750.     END; {of not replacing}
  1751.     {Advance counter to make a new unique sectionID for this }
  1752.     { document. It is not required that you equate section IDs }
  1753.     { with resources.}
  1754.     thisDocument^.nextSectionID := thisDocument^.nextSectionID + 1;
  1755.     {create a publisher section}
  1756.     sectionErr := NewSection(reply.container,
  1757.                                      thisDocument^.fileSpecPtr,
  1758.                                       stPublisher,
  1759.                                      thisDocument^.nextSectionID,
  1760.                                       pumOnSave, thisSectionH);
  1761.     IF (sectionErr <> noErr) & (sectionErr <> multiplePublisherWrn) 
  1762.             & (sectionErr <> notThePublisherWrn) THEN
  1763.         MyErrHandler(sectionErr);
  1764.     resID := thisDocument^.nextSectionID;
  1765.     {add this section/alias pair to app's internal bookkeeping}
  1766.     MyAddSectionAliasPair(thisDocument, thisSectionH, resID);
  1767.     {write out first edition}
  1768.     DoWriteEdition(thisSectionH);
  1769.     {Remember that the section and alias records need to be }
  1770.     { saved as resources when the user saves the document.}
  1771.     {set the function result appropriately}
  1772.     DoNewPublisher := MyGetLastError;
  1773. END; 
  1774.  
  1775.  
  1776. Opening an Edition Container to Write Data
  1777.  
  1778. Several routines are required to write (publish) data from a publisher to an edition container. (For information on creating an edition container, see the previous section.) Before writing data to an edition, you must use the OpenNewEdition function. This function should be used only for a publisher within a document. Use this function to initiate the writing of data to an edition.
  1779. err := OpenNewEdition(publisherSectionH, fdCreator,
  1780.                              publisherSectionDocument, refNum);
  1781. A user may try to save a document containing a publisher that is unable to write its data to an edition—because another publisher (that shares the same edition) is writing, another subscriber (that shares the same edition) is reading, or a publisher located on another computer is registered to the section. In such a case, you may decide to refrain from writing to the edition so that the user does not have to wait. You should also refrain from displaying an error to the user. The contents of the publisher are saved to disk with the document. The next time that the user saves the document, you can write the publisher data to the edition. You should display an alert box to discourage users from making multiple copies of the same publisher and pasting them in the same or other documents (see “Duplicating Publishers and Subscribers” on page 2-58).
  1782. If a user clicks Send Edition Now within the publisher options dialog box (to write publisher data to an edition manually), and the publisher is unable to write its data to its edition (for any of the reasons outlined above), you should display an error message.
  1783. After you are finished writing data to an edition, use the CloseEdition function to close the edition.
  1784. Listing 2-5 illustrates how to write data to an edition. For an existing edition container, you must open the edition, write each format using the WriteEdition function, and close the edition using the CloseEdition function. This listing shows how to write text only. If the edition is written successfully, subscribers receive Section Read events.
  1785.  
  1786. Listing 2-5    
  1787. Writing data to an edition
  1788.  
  1789. PROCEDURE DoWriteEdition(thePublisher: SectionHandle);
  1790. VAR
  1791.     eRefNum:                    EditionRefNum;
  1792.     openErr:                    OSErr;
  1793.     writeErr:                    OSErr;
  1794.     closeErr:                    OSErr;
  1795.     thisDocument:                    MyDocumentInfoPtr;
  1796.     textHandle:                    Handle;
  1797. BEGIN
  1798.     {find out which document this section belongs to}
  1799.     thisDocument := MyFindDocument(thePublisher);
  1800.     {open edition for writing}
  1801.     openErr := OpenNewEdition(thePublisher, kAppSignature,
  1802.                                           thisDocument^.fileSpecPtr, eRefNum);
  1803.     IF openErr <> noErr THEN
  1804.         MyErrHandler(openErr);    {handle error and exit}
  1805.     {get the text data to write}
  1806.     textHandle := MyGetTextInSection(thePublisher, thisDocument);
  1807.     {write out text data}
  1808.     HLock(textHandle);
  1809.     writeErr := WriteEdition(eRefNum, 'TEXT', textHandle^,
  1810.                                        GetHandleSize(textHandle));
  1811.     HUnLock(textHandle);
  1812.     IF writeErr <> noErr THEN
  1813.     BEGIN
  1814.         {There were problems writing; simply close the edition. }
  1815.         { When successful = FALSE, the edition data <> section }
  1816.         { data. Note: this isn't fatal or bad; it just means }
  1817.         { that the data wasn't written and no Section Read events }
  1818.         { will be generated.}
  1819.         closeErr := CloseEdition(eRefNum, FALSE);
  1820.     END 
  1821.     ELSE
  1822.     BEGIN
  1823.         {The write was successful; now close the edition. }
  1824.         { When successful = TRUE, the edition data = section data.}
  1825.         { This edition is now available to any subscribers. }
  1826.         { Section Read events will be sent to current subscribers.}
  1827.         closeErr := CloseEdition(eRefNum, TRUE);
  1828.     END;
  1829. END; 
  1830.  
  1831.  
  1832. Creating a Subscriber
  1833.  
  1834. You need to create a Subscribe To menu command in the Edit menu. When a user chooses Subscribe To from this menu, your application should display the subscriber dialog box on the user’s screen.
  1835. Use the NewSubscriberDialog function to display the subscriber dialog box on the user’s screen. This function is similar to the CustomGetFile procedure described in the chapter “Standard File Package” in Inside Macintosh: Files.
  1836. To create a subscriber, you must get information from the user, such as the name of the edition being subscribed to. The dialog box displays a listing of all available editions and allows the user to see a preview (thumbnail sketch) of the edition selected. Figure 2-12 shows a sample subscriber dialog box.
  1837.  
  1838. Figure 2-12    A sample subscriber dialog box
  1839.  
  1840. The subscriber dialog box allows the user to choose an edition to subscribe to. The NewSubscriberDialog function handles all user interaction until a user clicks Subscribe or Cancel. When a user selects an edition container, the Edition Manager accesses the preview for the edition container (if it is available) and displays it.
  1841. You pass a new subscriber reply record as a parameter to the NewSubscriberDialog function.
  1842. TYPE        NewSubscriberReply =
  1843.         RECORD
  1844.             canceled:                Boolean;                {user clicked Cancel}
  1845.             formatsMask:                SignedByte;                {formats required}
  1846.             container:                EditionContainerSpec;                        {initially, default }
  1847.                                             { name & location of edition }
  1848.                                             { to subscribe to; on return, }
  1849.                                             { edition name & location }
  1850.                                             { chosen by the user}
  1851.         END;
  1852. The canceled field returns a Boolean value of TRUE if the user clicked Cancel. To indicate which edition format types (text, graphics, or sound) your application can read, you set the formatsMask field to one or more of these constants:
  1853. CONST        kPICTformatMask                        = 1;                    {can subscribe to 'PICT'} 
  1854.         kTEXTformatMask                        = 2;                    {can subscribe to 'TEXT'}
  1855.         ksndFormatMask                        = 4;                    {can subscribe to 'snd '}
  1856. To support a combination of formats, add the constants together. For example, a formatsMask of 3 displays both graphics and text edition format types in the subscriber dialog box.
  1857. The container field is of data type EditionContainerSpec. You must initialize the container field with the default edition volume reference number, directory ID, filename, and part. To do so, use the GetLastEditionContainerUsed function to obtain the name of the last edition displayed in the dialog box.
  1858. err := GetLastEditionContainerUsed(container);
  1859. This function returns the last edition container for which a new section was created using the NewSection function. If there is no last edition, or if the edition was deleted, GetLastEditionContainerUsed still returns the correct volume reference number and directory ID to use, but leaves the filename blank and returns the fnfErr result code.
  1860. The container field is of data type EditionContainerSpec.
  1861. TYPE EditionContainerSpec = 
  1862.     RECORD
  1863.         theFile:                        FSSpec;                    {file containing edition }
  1864.                                                     { data}
  1865.         theFileScript:                        ScriptCode;                    {script code of filename}
  1866.         thePart:                        LongInt;                    {which part of file, }
  1867.                                                     { always kPartsNotUsed}
  1868.         thePartName:                        Str31;                    {reserved}
  1869.         thePartScript:                        ScriptCode;                    {reserved}
  1870.     END;
  1871. The field theFile is of type FSSpec. See Inside Macintosh: Files for further information on file system specification records.
  1872. After filling in the fields of the new subscriber reply record, pass it as a parameter to the NewSubscriberDialog function, which displays the subscriber dialog box.
  1873. err := NewSubscriberDialog(reply);
  1874. After displaying the subscriber dialog box, call the NewSection function to create the section record and the alias record. See “Creating the Section Record and Alias Record” beginning on page 2-15 for detailed information.
  1875. If the subscriber is set up to receive new editions automatically (not manually), the Edition Manager sends your application a Section Read event. Whenever your application receives a Section Read event, it should read the contents of the edition into the subscriber.
  1876. Listing 2-6 illustrates how to create a subscriber. As described earlier, you must set up and display the subscriber dialog box to allow the user to subscribe to any of the available editions. After your application creates a subscriber, your application receives a Section Read event to read in the data being subscribed to. Be sure to add the newly created section to your list of sections for this file. There are many different techniques for creating subscribers and unique IDs; this listing displays one technique.
  1877.  
  1878. Listing 2-6    
  1879. Creating a subscriber
  1880.  
  1881. PROCEDURE DoNewSubscriber(thisDocument: MyDocumentInfoPtr);
  1882. VAR
  1883.     getLastErr:                    OSErr;
  1884.     dialogErr:                    OSErr;
  1885.     sectionErr:                    OSErr;
  1886.     resID:                    Integer;
  1887.     thisSectionH:                    SectionHandle;
  1888.     reply:                    NewSubscriberReply;
  1889. BEGIN
  1890.     {put default edition name into reply record}
  1891.     getLastErr := GetLastEditionContainerUsed(reply.container);
  1892.     {can subscribe to pictures or text}
  1893.     reply.formatsMask := kPICTformatMask + kTEXTformatMask;
  1894.     {display dialog box & let user select edition to subscribe to}
  1895.     dialogErr := NewSubscriberDialog(reply);
  1896.     IF dialogErr <> noErr THEN 
  1897.         MyErrHandler(dialogErr);                                    {handle error and exit}
  1898.     IF reply.canceled THEN                                         
  1899.         EXIT(DoNewSubscriber);                                    {do nothing if user canceled}
  1900.     {Advance counter to make a new unique sectionID for this }
  1901.     { document. It is not necessary to equate section IDs with }
  1902.     { resources.}
  1903.     thisDocument^.nextSectionID := thisDocument^.nextSectionID + 1;
  1904.     {create a subscriber section}
  1905.     sectionErr := NewSection(reply.container,
  1906.                                       thisDocument^.fileSpecPtr,
  1907.                                      stSubscriber, 
  1908.                                      thisDocument^.nextSectionID,
  1909.                                       sumAutomatic, thisSectionH);
  1910.     IF sectionErr <> noErr THEN
  1911.         MyErrHandler(sectionErr);    {handle error and exit}
  1912.     resID := thisDocument^.nextSectionID;
  1913.     {add this section/alias pair to app's internal bookkeeping}
  1914.     MyAddSectionAliasPair(thisDocument, thisSectionH, resID);
  1915.     {Remember that you will receive a Section Read event to read }
  1916.     { in the edition that you just subscribed to because the }
  1917.     { initial mode is set to sumAutomatic.}
  1918.     {Remember that the section and alias records need to be saved } 
  1919.     { as resources when the user saves the document.}
  1920. END; 
  1921.  
  1922.  
  1923. Opening an Edition Container to Read Data
  1924.  
  1925. Before reading data from an edition, you must use the OpenEdition function. Your application should only use this function for a subscriber. Use this function to initiate the reading of data from an edition.
  1926. err := OpenEdition(subscriberSectionH, refNum);
  1927. As a precaution, you should retain the old data until the user can no longer undo. This allows you to undo changes if the user requests it.
  1928. Your application can supply a procedure such as DoReadEdition to read in data from the edition to a subscriber. When your application opens a document containing a subscriber that is set up to receive new editions automatically, the Edition Manager sends you a Section Read event if the edition has been updated. The Section Read event supplies the handle to the section that requires updating. Listing 2-7, shown in the next section, provides an example of reading data from an edition.
  1929.  
  1930. Choosing Which Edition Format to Read
  1931.  
  1932. After your application opens the edition container for a subscriber, it can look in the edition for formats that it understands. To accomplish this, use the EditionHasFormat function.
  1933. err := EditionHasFormat(whichEdition, whichFormat, formatSize);
  1934. The EditionHasFormat function returns the noTypeErr result code if a requested format is not available. If the requested format is available, this function returns the noErr result code, and the formatSize parameter contains the size of the data in the specified format or kFormatLengthUnknown (–1), which signifies that the size is unknown.
  1935. Note
  1936. The Translation Manager (if it is available) attempts implicit translation under certain circumstances. For instance, it does so when your application attempts to read from an edition a format type that is not in the edition. In this case, the Translation Manager attempts to translate the data into the requested format. For more information, see the chapter “Translation Manager” in Inside Macintosh: More Macintosh Toolbox.u
  1937.  
  1938. After your application opens the edition container and determines which formats it wants to read, call the ReadEdition function to read in the edition data. See “Reading and Writing Edition Data” on page 2-27 for detailed information.
  1939. After you have completed writing the edition data into the subscriber section, call the CloseEdition function to close the edition. See “Closing an Edition” on page 2-28 for detailed information.
  1940. Listing 2-7 illustrates how to read data from an edition. As described earlier, you must open the edition, determine which formats to read, use the ReadEdition function to read in data, and then use the CloseEdition function to close the edition. This listing shows how to read only text.
  1941.  
  1942. Listing 2-7    Reading in edition data
  1943.  
  1944. PROCEDURE DoReadEdition(theSubscriber: SectionHandle);
  1945. VAR
  1946.     eRefNum:                        EditionRefNum;
  1947.     openErr:                        OSErr;
  1948.     readErr:                        OSErr;
  1949.     closeErr:                        OSErr;
  1950.     thisDocument:                        MyDocumentInfoPtr;
  1951.     textHandle:                        Handle;
  1952.     formatLen:                        Size;
  1953. BEGIN
  1954.     {find out which document this section belongs to}
  1955.     thisDocument := MyFindDocument(theSubscriber);
  1956.     {open the edition for reading}
  1957.     openErr := OpenEdition(theSubscriber, eRefNum);
  1958.     IF openErr <> noErr THEN
  1959.         MyErrHandler(openErr);                                {handle error and exit}
  1960.     {look for 'TEXT' format}
  1961.     IF EditionHasFormat(eRefNum, 'TEXT', formatLen) = noErr THEN
  1962.     BEGIN
  1963.         {get the handle of location to read to}
  1964.         textHandle := MyGetTextInSection(theSubscriber, 
  1965.                                                   thisDocument);
  1966.         SetHandleSize(textHandle, formatLen);
  1967.         HLock(textHandle);
  1968.         readErr := ReadEdition(eRefNum, 'TEXT', textHandle^, 
  1969.                                       formatLen);
  1970.         MyUpdateSubscriberText(theSubscriber, textHandle, readErr);
  1971.         HUnLock(textHandle);
  1972.         IF readErr = noErr THEN
  1973.         BEGIN        
  1974.             {The read was successful; now close the edition. When }
  1975.             { successful = TRUE, the section data = edition data.}
  1976.             closeErr := CloseEdition(eRefNum, TRUE);
  1977.             EXIT(DoReadEdition);
  1978.         END;                                                
  1979.     END;        {of EditionHasFormat}
  1980.     {'TEXT' format wasn't found or read error; just close }
  1981.     { the edition. FALSE tells the Edition Manager that your }
  1982.     { application did not get the latest edition.}
  1983.     closeErr := CloseEdition(eRefNum, FALSE);
  1984. END; 
  1985.  
  1986. Using Publisher and Subscriber Options
  1987.  
  1988. You can allow users to set several special options associated with publishers and subscribers. To set these preferences, users change settings in two dialog boxes provided by the Edition Manager: publisher options and subscriber options. To make these dialog boxes available to the user, provide a command in the Edit menu that toggles between Publisher Options (when the user has selected a publisher within a document) and Subscriber Options (when a user has selected a subscriber within a document). 
  1989. When a user chooses one of these menu commands, you need to display the appropriate dialog box. Use the SectionOptionsDialog function to display the publisher options or subscriber options dialog box on the user’s screen.
  1990. err := SectionOptionsDialog(reply);
  1991. Each dialog box contains information regarding the section and its edition. Figure 2-13 shows the publisher options dialog box with the update mode set to On Save. 
  1992.  
  1993. Figure 2-13    The publisher options dialog box with update mode set to On Save
  1994.  
  1995. Figure 2-14 shows the publisher options dialog box with the update mode set to Manually.
  1996.  
  1997. Figure 2-14    The publisher options dialog box with update mode set to Manually 
  1998.  
  1999. As a shortcut for the user, you should display the publisher options dialog box when the user double-clicks a publisher section in a document. 
  2000. Figure 2-15 shows the subscriber options dialog box with the update mode set to Automatically. 
  2001.  
  2002. Figure 2-15    The subscriber options dialog box with update mode set to Automatically 
  2003.  
  2004. Figure 2-16 shows the subscriber options dialog box with the update mode set to Manually.
  2005.  
  2006. Figure 2-16    The subscriber options dialog box with update mode set to Manually
  2007.  
  2008. As a shortcut for the user, you should display the subscriber options dialog box when the user double-clicks a subscriber section in a document.
  2009. You pass a section options reply record as a parameter to the SectionOptionsDialog function.
  2010. TYPE SectionOptionsReply = 
  2011.     RECORD
  2012.         canceled:                Boolean;                        {user clicked Cancel}
  2013.         changed:                Boolean;                        {changed section record}
  2014.         sectionH:                SectionHandle;                         {handle to the specified }
  2015.                                                 { section record}
  2016.         action:                ResType;                        {action codes}
  2017.     END;
  2018. Set the sectionH parameter to the handle to the section record for the section the user selected.
  2019. Upon return of the SectionOptionsDialog function, the canceled and changed fields are set. If the canceled field is set to TRUE, the user clicked Cancel. Otherwise, this field is set to FALSE. If the changed field is set to TRUE, the section record is changed. For example, the user may have changed the update mode.
  2020. The SectionOptionsDialog function returns in the action parameter the code for one of five user actions. The function dismisses the publisher and subscriber options dialog boxes after the user clicks a button.
  2021. n    Action code is 'read' for a click of the Get Edition Now button.
  2022. n    Action code is 'writ' for a click of the Send Edition Now button.
  2023. n    Action code is 'goto' for a click of the Open Publisher button.
  2024. n    Action code is 'cncl' for a click of the Cancel Publisher or Cancel Subscriber button.
  2025. n    Action code is '    ' ($20202020) for a click of the OK button. 
  2026. Listing 2-8 shows an example of how your application can respond to the action codes received from the section options reply record. You can use several different techniques for this purpose; this listing shows one technique.
  2027.  
  2028. Listing 2-8    Responding to action codes
  2029.  
  2030. PROCEDURE DoOptionsDialog(theSection: SectionHandle);
  2031. VAR
  2032.     reply:                        SectionOptionsReply;
  2033.     theEditionInfo:                        EditionInfoRecord;
  2034.     action:                        ResType;
  2035.     sodErr, geiErr:                        OSErr;
  2036.     gpiErr, gpsErr:                        OSErr;
  2037.  
  2038. BEGIN
  2039.     reply.sectionH := theSection;
  2040.     {display options dialog box}
  2041.     sodErr := SectionOptionsDialog(reply);
  2042.     {determine what the user did and handle appropriately}
  2043.     IF reply.canceled THEN                                {user selected the Cancel button}
  2044.         EXIT(DoOptionsDialog);
  2045.     IF reply.changed THEN
  2046.         {the section record has changed; make note of this}
  2047.         MySectionHasChanged(theSection);
  2048.         {if you customize, you may want to do some }
  2049.         { post-processing now}
  2050.     {get the action code}
  2051.     action := reply.action;
  2052.     IF (action = 'read') THEN
  2053.     BEGIN            {user selected Get Edition Now button}
  2054.         DoReadEdition(theSection);
  2055.         EXIT(DoOptionsDialog);
  2056.     END;
  2057.     IF (action = 'writ') THEN
  2058.     BEGIN            {user selected Send Edition Now button}
  2059.         DoWriteEdition(theSection);
  2060.         EXIT(DoOptionsDialog);
  2061.     END;
  2062.     IF (action = 'goto') THEN
  2063.     BEGIN            {user selected Open Publisher button}
  2064.         geiErr := GetEditionInfo(theSection, theEditionInfo);
  2065.         IF geiErr <> noErr THEN 
  2066.             MyErrHandler(geiErr);    {handle error and exit}
  2067.         gpsErr := GotoPublisherSection(theEditionInfo.container);
  2068.         IF gpsErr <> noErr THEN
  2069.             MyErrHandler(gpsErr);    {handle error and exit}
  2070.         EXIT(DoOptionsDialog);
  2071.     END;
  2072.     IF (action = 'cncl') THEN
  2073.     BEGIN     {User selected Cancel Publisher or Cancel Subscriber }
  2074.         { button. Call the UnRegisterSection function and dispose }
  2075.         { of the section record and alias record.}
  2076.         EXIT(DoOptionsDialog);
  2077.     END;
  2078. END;
  2079. The following sections describe the features of the publisher and subscriber options dialog boxes.
  2080.  
  2081. Publishing a New Edition While Saving or Manually
  2082.  
  2083. By default, your application should write publisher data to an edition each time the user saves the document and the contents of the publisher differ from the latest edition. In the publisher options dialog box, the user can choose to write new data to an edition each time the document is saved (by clicking On Save) or only upon the user’s specific request (by clicking Manually).
  2084. When the update mode is set to manual, a user must click the Send Edition Now button in the publisher options dialog box to write publisher data to an edition. When a user clicks this button, the section options reply record contains the action code 'writ'. In this case, you should write out the new edition. Writing to an edition manually is useful when a user tends to save a document numerous times while revising it.
  2085. Each time the user saves the document, check the update mode of the publisher section. If the publisher section sends its data to an edition when the document is saved, check whether the publisher data has changed since it was last written to the edition. If so, write the publisher’s data to the new edition.
  2086. In addition, you may also support a Stop All Editions menu command to provide a method for temporarily suspending all update activity. See “Introduction to Publishers, Subscribers, and Editions” beginning on page 2-4 for additional information.
  2087.  
  2088. Subscribing to an Edition Automatically or Manually
  2089.  
  2090. By default, your application should subscribe to an edition each time new edition data becomes available. In the subscriber options dialog box, the user can choose to read new data from an edition as the data is available (by clicking Automatically) or only upon the user’s specific request (by clicking Manually).
  2091. When the update mode is set to manual, the user must click the Get Edition Now button in the subscriber options dialog box to receive new editions. When a user clicks this button, the section options reply record contains the action code 'read'. In this case, you should read in the new edition. See “Opening an Edition Container to Read Data” beginning on page 2-41 for detailed information.
  2092. When the update mode is set to automatic, your application receives a Section Read event each time a new edition becomes available. In response, you should read the new edition data beginning with the OpenEdition function.
  2093. Your application does not receive Section Read events for subscribers that receive new editions manually.
  2094. You may also support a Stop All Editions menu command to provide a method for temporarily suspending all update activity. See “Introduction to Publishers, Subscribers, and Editions” beginning on page 2-4 for additional information.
  2095.  
  2096. Canceling Sections Within Documents
  2097.  
  2098. The option of canceling publishers and subscribers is available to the user through the Cancel Publisher and Cancel Subscriber buttons in the corresponding options dialog boxes. When the user clicks one of these buttons, the action code of the section options reply record is 'cncl'. See “Relocating an Edition” on page 2-60 for additional information on canceling a section.
  2099. When a user cancels a section (either a publisher or subscriber) and then saves the document, or when a user closes an untitled document (which contains newly created sections) without saving it, you must unregister each corresponding section record and alias record using the UnRegisterSection function. In addition, you should also delete the section record and alias record using the DisposeHandle procedure. See Inside Macintosh: Memory for additional information on the DisposeHandle procedure.
  2100. When a user cancels a publisher section and then saves the document, or when a user closes an untitled document (which contains newly created publishers) without saving it, you must also delete any corresponding edition containers (in addition to deleting section records and alias records).
  2101. Do not delete an edition container file, section record, or alias record until the user saves the document; the user may decide to undo changes before saving the document.
  2102. To locate the appropriate edition container to be deleted (before you use the UnRegisterSection function), use the GetEditionInfo function.
  2103. err := GetEditionInfo(sectionH, editionInfo);
  2104. The editionInfo parameter is a record of data type EditionInfoRecord.
  2105. TYPE EditionInfoRecord = 
  2106.     RECORD
  2107.         crDate:                TimeStamp;                            {date edition container }
  2108.                                                     { was created}
  2109.         mdDate:                TimeStamp;                            {date of last change}
  2110.         fdCreator:                OSType;                            {file creator}
  2111.         fdType:                OSType;                            {file type}
  2112.         container:                EditionContainerSpec;                            {the edition}
  2113.     END;
  2114. The GetEditionInfo function returns the edition container as part of the edition information.
  2115. The crDate field contains the creation date of the edition. The mdDate field contains the modification date of the edition.
  2116. The fdType and the fdCreator fields are the type and creator of the edition file. The container field includes a volume reference number, directory ID, filename, script, and part number for the edition.
  2117. To remove the edition container, use the DeleteEditionContainerFile function.
  2118. err := DeleteEditionContainerFile(editionFile);
  2119.  
  2120. Locating a Publisher Through a Subscriber
  2121.  
  2122. The user can locate a publisher from a subscriber within a document by clicking the Open Publisher button in the subscriber options dialog box. As a shortcut, Apple suggests that you also allow the user to locate a publisher by selecting a subscriber in a document and pressing Option–double-click.
  2123. When the action code of the SectionOptionsReply record is 'goto', use the GoToPublisherSection function.
  2124. err := GoToPublisherSection(container);
  2125. The GoToPublisherSection function locates the correct document by resolving the alias in the edition, and it launches the document’s application if necessary (the Edition Manager sends an Open Documents event). The Edition Manager then sends the publishing application a Section Scroll event. If the document containing the requested publisher is located on the same computer as its subscriber, the document opens and scrolls to the location of the publisher. If the document containing the requested publisher is located on a shared volume (using file sharing), the document opens and scrolls to the location of the publisher only if the user has privileges to open the document from the Finder.
  2126. You need to provide the GoToPublisherSection function with the edition container. To accomplish this, use the GetEditionInfo function. See the previous section, “Canceling Sections Within Documents,” for information on the GetEditionInfo function.
  2127.  
  2128. Renaming a Document Containing Sections
  2129.  
  2130. If a user renames a document that contains sections by choosing Save As from the File menu, or if a user pastes a portion of a document that contains a section into another document, use the AssociateSection function.
  2131. Use the AssociateSection function to update the alias record of a registered section.
  2132. err := AssociateSection (sectionH, newSectionDocument);
  2133. The AssociateSection function internally calls the UpdateAlias function. It is also possible to update the alias record using the Alias Manager (see the chapter “Alias Manager” in Inside Macintosh: Files for additional information).
  2134.  
  2135. Displaying Publisher and Subscriber Borders
  2136.  
  2137. Each publisher and subscriber within a document should have a border that appears when a user selects the contents of these sections. You should display a publisher border as three pixels wide with 50 percent gray lines and a subscriber border as three pixels wide with 75 percent gray lines. Separate the contents of the section from the border itself with one pixel of white space. To create your borders, you should use patterns, not colors. Depending on the user’s monitor type, colors may not be distinguishable.
  2138. In general, borders for publishers and subscribers should behave like the borders of 'PICT' graphics in a word-processing document. A border should appear when the user clicks the content area of a publisher or a subscriber and disappear when 
  2139. the user clicks outside the content area of a section. You can also make all publisher 
  2140. and subscriber borders appear or disappear by implementing an optional 
  2141. Show/Hide Borders menu command. 
  2142. Figure 2-17 displays the Edition Manager Show/Hide Borders menu command in the Edit menu.
  2143.  
  2144. Figure 2-17    Edit menu with Show/Hide Borders menu command
  2145.  
  2146. Depending on your application, you may choose to include resize handles or similar components in your borders. See “Object-Oriented Graphics Borders” on page 2-56 for an example of resize handles.
  2147. Whenever a user selects a portion of a publisher or sets the insertion point within a publisher, you should display the border as 50 percent gray. A user can copy the contents of a publisher or subscriber without copying the section itself by selecting the data, copying, and then pasting the data in a new location. A user can cut and paste a selection that contains an entire publisher or subscriber, but you should discourage users from making multiple copies of a publisher. See “Duplicating Publishers and Subscribers” on page 2-58 for detailed information.
  2148. When the user modifies a publisher, your application should grow or shrink its border to accommodate the new dimension of the section.
  2149. You should display only one publisher border within a document at a time. If a cursor is inserted within a publisher that is contained within a larger publisher, you should display only the smaller, internal publisher border. If it is absolutely necessary to display all section borders within a document at the same time, you can create a Show/Hide Borders menu item. 
  2150. You do not need to provide support for publishers contained within other publishers. If you do not, you should dim the Create Publisher menu command (to indicate that it is not selectable) when a user attempts to create a publisher within an existing publisher.
  2151. Figure 2-18 shows the recommended border behavior for publishers. The top window shows a publisher with its borders displayed. The middle window shows how the borders look when a user selects some of the contents of a section. The bottom window shows how the borders look when a user selects data within a document that includes a publisher section.
  2152.  
  2153. Figure 2-18    Publisher borders
  2154.  
  2155. Figure 2-19 shows the recommended border behavior for subscribers. The top window shows a subscriber with its borders displayed. The middle window shows how the borders look when a user selects the contents of a section. The bottom window shows how the borders look when a user selects data within a document that includes a subscriber section.
  2156.  
  2157. Figure 2-19    Subscriber borders
  2158.  
  2159. If a user tries to select only a portion of a subscriber, you should highlight the entire contents of the subscriber. A user cannot edit the data in a subscriber. See “Modifying a Subscriber” on page 2-59 for detailed information.
  2160. If a user cancels a section using the publisher or subscriber options dialog box, your application should leave the contents of the section within the document, but you should be sure to remove the borders from this data, as it is no longer considered a section.
  2161. Generally, the appearance and function of publisher and subscriber borders should be the same across different applications. The following sections entitled “Text Borders,” “Spreadsheet Borders,” “Object-Oriented Graphics Borders,” and “Bitmapped Graphics Borders” describe specialized features for publisher and subscriber borders in word-processing, spreadsheet, or graphics applications. 
  2162.  
  2163. Text Borders
  2164.  
  2165. In word-processing documents, a publisher may contain other publishers. However, one publisher should not overlap another publisher. You should display only one publisher border at a time. If an insertion point is placed within a publisher that is encompassed by another larger publisher, you should display only the smaller internal publisher border.
  2166. In exceptional cases, it may be necessary to display more than one publisher or subscriber border at a time. For example, a publisher may consist of a paragraph that includes a marker for a footnote. The data contained within the footnote should also be considered part of the publisher. When a user selects the paragraph, you should simultaneously display a border around the footnote.
  2167. The border of a publisher that contains text should be located between characters within the text. The insertion point, when placed on such a boundary, should gravitate toward the publisher. That is, a click in front (to the left) of a publisher border should place the cursor inside the publisher, so that subsequent typing goes inside the publisher. Clicking at the end (to the right) of a publisher border should also place the cursor inside the publisher.
  2168. Whenever two separate borders are adjacent, the boundary click should go in between them. This is also true for a border that is next to other nontextual aspects of a document, such as 'PICT' graphics or page breaks.
  2169. When a user removes information from a publisher that contains text data, you should resize the border so that it becomes smaller. When a user adds information to the publisher, you should enlarge the border to accommodate the new text. The insertion point should remain within the publisher. 
  2170. If a user highlights the entire contents of a publisher and then chooses Cut from the Edit menu, you should not delete the publisher border within the document. The user may intend to delete the existing publisher data and replace it with new data, or the user may want to move the entire publisher and its data to a new location. Figure 2-20 shows 
  2171. this state.
  2172.  
  2173. Figure 2-20    A publisher with contents removed
  2174.  
  2175. You should leave the cursor inside the small publisher border for further typing. If the user inserts the cursor in a new location (instead of typing data inside the existing border), you need to remove the empty publisher border from the document to allow the user to move the publisher. This effectively deletes the publisher from the document. If the user pastes the publisher that is currently held in the scrap, you should re-create its border. If the user cuts or copies other data from the document before pasting the publisher from the scrap, the publisher should be removed from the scrap.
  2176.  
  2177. Spreadsheet Borders
  2178.  
  2179. Borders around spreadsheet data or other data in arrays should look and behave very much like text borders. Figure 2-21 shows a typical border within a spreadsheet document.
  2180.  
  2181. Figure 2-21    A publisher border within a spreadsheet document
  2182.  
  2183. Note that the border goes below the column headers (A, B, C, D) and to the right of the row labels (1, 2, 3, 4)—it should not overlap these cell boundaries. The border at the bottom and the border on the right side can be placed within the adjacent cells (outside of the cells that constitute the publisher).
  2184. Unlike borders in word-processing applications, borders in spreadsheet documents (or other documents with array data) can overlap. That is, a user can select a row of cells to be a publisher and an overlapping column of those cells to be another publisher. You should never display more than one publisher border at a time. When a user selects a spreadsheet cell that is part of more than one publisher, you should display only the border of the publisher that was last edited. (This can be accomplished by comparing the modification dates of the publishers.)
  2185. If it is absolutely necessary to display all section borders within a document at the same time, you can create a Show/Hide Borders command in the Edit menu to toggle all borders on and off.
  2186. When data is added to or deleted from a publisher that consists of a spreadsheet cell or other array, you should resize its border to accommodate the addition or deletion of data. A publisher should behave like a named range in a spreadsheet. For example, if a user cuts a row within a publisher that consists of a named range in a spreadsheet, you should shrink the publisher data and its border correspondingly.
  2187. When a user cuts a publisher and its entire contents within a spreadsheet document, the entire section should be held in the scrap. Do not leave an empty publisher border in a spreadsheet (as recommended for text borders). If a user attempts to paste a copy of an existing publisher, you should warn the user by displaying an alert box (see “Duplicating Publishers and Subscribers” on page 2-58).
  2188.  
  2189. Object-Oriented Graphics Borders
  2190.  
  2191. In an object-oriented drawing application, the publisher border should fit just around the selected objects.
  2192. You can provide resize handles that appear with all drawing objects to allow the user to resize the border of a publisher. Figure 2-22 shows a publisher border with resize handles.
  2193.  
  2194. Figure 2-22    A publisher border with resize handles
  2195.  
  2196. An application can make publisher borders appear to float over the area the user publishes. The border acts like a clipping rectangle—anything within the border becomes the publisher. Figure 2-23 shows a publisher that contains clipped graphics and its subscriber in another application.
  2197. A user can create publishers and subscribers that overlap each other. Thus, borders may overlap and it may no longer be possible to turn on a particular border when the user clicks within a publisher. Drawing applications should provide a menu command, Show Borders, that toggles to Hide Borders. This command should allow users to turn all publisher and subscriber borders on or off.
  2198.  
  2199. Figure 2-23    
  2200. A publisher and subscriber with clipped graphics
  2201.  
  2202.  
  2203. Bitmapped Graphics Borders
  2204.  
  2205. Creating a border around bitmapped graphics in applications is similar to doing so in object-oriented drawing applications. The border appears around the selected area. The user can create overlapping publishers and subscribers in bitmapped graphics applications. You need to provide a Show/Hide Borders command to allow users to turn all borders on and off.
  2206.  
  2207.  
  2208. Duplicating Publishers and Subscribers
  2209.  
  2210. Whenever a user clicks a publisher or subscriber border, you should change the contents of the section to a selected state. You should discourage users from making multiple copies of a publisher and pasting them in the same or other documents, because the contents of the edition would be difficult or impossible to predict. Multiple copies of the same publisher also contain the same control block value. See “Creating and Registering a Section” on page 2-74 for detailed information on control blocks.
  2211. When a user attempts to create a copy of a publisher that already exists, you should display an alert box such as the one shown in Figure 2-24.
  2212.  
  2213. Figure 2-24    Creating multiple publishers alert box
  2214.  
  2215. When a user attempts to save a document that contains multiple copies of the same publisher, display an alert box such as the one shown in Figure 2-25.
  2216.  
  2217. Figure 2-25    Saving multiple publishers alert box
  2218.  
  2219. If a user decides to ignore your alert box, your application should still save the document, but you should continue to display this error message every time the user saves this document.
  2220. A user can modify the contents of any duplicate publisher, but the contents of the edition will be whichever publisher was the last to write.
  2221. When a user chooses to copy and paste or duplicate a section, use the HandToHand function (described in Inside Macintosh: Memory) to duplicate the section record and alias record. Set the alias field of the cloned section record to the handle of the cloned alias record and generate a unique section identification number for it. In addition, you should also place the section data, section record, and alias record in the scrap.
  2222. Use the RegisterSection function (described in “Opening and Closing a Document Containing Sections” on page 2-22) to register the cloned section’s section record.
  2223. A user can select the contents of a publisher without selecting the border and copy just the data to a new location. In this case, the user has simply copied data (and not the publisher). Do not create a border for this data in the new location.
  2224.  
  2225. Modifying a Subscriber
  2226.  
  2227. When the user selects data or clicks the data area of a subscriber, you should highlight the entire contents of the subscriber using inverse video. Although you shouldn’t allow a user to edit the information in a subscriber, you can allow a user to make global adornments to subscribers. In other words, users can change the font, size, or other characteristics of the entire subscriber. For example, a user might select a subscriber within a document and change all text from plain to bold. However, you should discourage users from modifying the individual elements contained within a subscriber—for example, by editing a sentence or rotating an individual graphic object.
  2228. Remember that each time a new edition arrives for a subscriber, any modifications that the user has introduced are overwritten. Global changes to a subscriber are much easier for your application to regenerate.
  2229. Note
  2230. Although adornments should be global and never partial, you may still need to give users the ability to select portions of a subscriber, for instance, when performing spell checking and search-and-replace operations.u
  2231.  
  2232. If you do allow a user to edit a subscriber section, provide an 
  2233. enable/disable editing option within the subscriber options dialog box using the SectionOptionsExpDialog function, described in “Customizing Dialog Boxes” beginning on the next page. When you allow a user to edit a subscriber, you should change the subscriber from a selected state to editable data.
  2234. Because a user can modify a publisher just like any other portion of a document, its subscriber may change in size as well as content. For example, a user may modify a publisher by adding two additional columns to a spreadsheet.
  2235.  
  2236.  
  2237. Relocating an Edition
  2238.  
  2239. In the Finder, users cannot move an edition across volumes. To relocate an edition, the user must first select its publisher and cancel the section (remember to remove the border). The user needs to republish and then select a new volume location for the edition. As a convenience for the user, you should retain the selection of all the publisher data after the user cancels the section to make it easy to republish the section.
  2240.  
  2241. Customizing Dialog Boxes
  2242.  
  2243. The expandable dialog box functions allow you to add items to the bottom of the dialog boxes, apply alternate mapping of events to item hits, apply alternate meanings to the item hits, and choose the location of the dialog boxes. See the chapter “Dialog Manager” in Inside Macintosh: Macintosh Toolbox Essentials and the chapter “Standard File Package” in Inside Macintosh: Files for additional information.
  2244. The expandable versions of these dialog boxes require five additional parameters. Use the NewPublisherExpDialog function to expand the publisher dialog box.
  2245. err := NewPublisherExpDialog (reply, where, expansionDITLresID, 
  2246.                                         dlgHook, filterProc, yourDataPtr);
  2247. Use the NewSubscriberExpDialog function to expand the subscriber dialog box.
  2248. err := NewSubscriberExpDialog (reply, where, expansionDITLresID,
  2249.                                          dlgHook, filterProc, yourDataPtr);
  2250. Use the SectionOptionsExpDialog function to expand the publisher options and the subscriber options dialog boxes.
  2251. err := SectionOptionsExpDialog (reply, where, expansionDITLresID,
  2252.                                           dlgHook, filterProc, yourDataPtr);
  2253. The reply parameter is a pointer to a NewPublisherReply, NewSubscriberReply, or SectionOptionsReply record, respectively.
  2254. You can automatically center the dialog box by passing (–1, –1) in the where parameter. 
  2255. The expansionDITLresID parameter should contain 0 or a valid item list ('DITL') resource ID. This integer is the resource ID of an item list whose items are appended to the end of the standard item list. The dialog items keep their relative positions, but they are moved as a group to the bottom of the dialog box. See the chapter “Dialog Manager” in Inside Macintosh: Macintosh Toolbox Essentials for additional information on item lists.
  2256. The filterProc parameter should be a pointer to an expandable modal-dialog filter function or NIL. An expandable modal-dialog filter function is similar to a modal-dialog filter function or event filter function except that an expandable modal-dialog filter function accepts two extra parameters. The ModalDialog procedure calls the expandable modal-dialog filter function you provide in this parameter. 
  2257.  
  2258. Providing a filter function enables you to map real events (such as a mouse-down event) to an item hit (such as clicking the Cancel button). For instance, you may want to map a keyboard equivalent to an item hit. See the chapter “Dialog Manager” in Inside Macintosh: Macintosh Toolbox Essentials for information on the ModalDialog procedure.
  2259. The dlgHook parameter should be a pointer to an expandable dialog hook function or NIL. An expandable dialog hook function is similar to a dialog hook function except that an expandable dialog hook function accepts an additional parameter. The NewSubscriberExpDialog, NewPublisherExpDialog, and SectionOptionsExpDialog functions call your expandable dialog hook function after each call to the ModalDialog procedure. The dialog hook function should take the appropriate action, such as filling in a checkbox. The itemOffset parameter to the procedure is the number of items in the item list before the expansion dialog items. You need to subtract the item offset from the item hit to get the relative item number in the expansion dialog item list. The expandable dialog hook function should return as its function result the absolute item number. 
  2260. When the Edition Manager displays subsidiary dialog boxes in front of another dialog box on the user’s screen, your dialog hook and event filter functions should check the refCon field in the WindowRecord data type (from the window field in the DialogRecord) to determine which window is currently in the foreground. The main dialog box for the NewPublisherExpDialog and the NewSubscriberExpDialog functions contains the following constant:
  2261. CONST            sfMainDialogRefCon                            = 'stdf';                {new publisher and }
  2262.                                                         { new subscriber}
  2263. The main dialog box for the SectionOptionsExpDialog function contains the following constant:
  2264. CONST            emOptionsDialogRefCon                                = 'optn';                {options dialog}
  2265. See “Summary of the Edition Manager” beginning on page 2-106 for additional constants. 
  2266. The yourDataPtr parameter is reserved for your use. It is passed back to your dialog hook and event filter function. This parameter does not have to be of type Ptr—it can be any 32-bit quantity that you want. In Pascal, you can pass yourDataPtr in register A6 , and declare your dialog hook and modal-dialog filter as local functions without the last parameter. The stack frame is set up properly for these functions to access their parent local variables. See the chapter “Standard File Package” in Inside Macintosh: Files for detailed information.
  2267. For the NewPublisherExpDialog and NewSubscriberExpDialog functions, all the pseudo-items for the Standard File Package—such as sfHookFirstCall(–1), sfHookNullEvent(100), sfHookRebuildList(101), and sfHookLastCall(–2)—can be used, as well as emHookRedrawPreview(150).
  2268. For the SectionOptionsExpDialog function, the only valid pseudo-items are sfHookFirstCall(–1), sfHookNullEvent(100), sfHookLastCall(–2), emHookRedrawPreview(150), emHookCancelSection(160), emHookGoToPublisher(161), emHookGetEditionNow(162), emHookSendEditionNow(162), emHookManualUpdateMode(163), and emHookAutoUpdateMode(164). See the chapter “Standard File Package” in Inside Macintosh: Files for information on pseudo-items.
  2269.  
  2270. Subscribing to Non-Edition Files
  2271.  
  2272. Using the Edition Manager, a subscriber can read data directly from another document, such as an entire 'PICT' file, instead of subscribing to an edition. This feature is for advanced applications that can set up bottleneck procedures for reading. Figure 2-26 shows a document that is subscribing directly to a 'PICT' file. 
  2273.  
  2274. Figure 2-26    Subscribing directly to a 'PICT' file
  2275.  
  2276. For each application, the Edition Manager keeps a pointer to a bottleneck function. The Edition Manager never opens or closes an edition container directly. Instead, the Edition Manager calls the current edition opener. The InitEditionPack function (described on page 2-74) sets up the current system opener function.
  2277. To override the standard opener function, create an opener function that contains the following parameters:
  2278. FUNCTION MyOpener (selector: EditionOpenerVerb; 
  2279.                          VAR PB: EditionOpenerParamBlock): OSErr;
  2280. Your opener needs to know which formats the file contains and how the data is supposed to be read or written. 
  2281. The opener function is passed an edition opener verb in the selector parameter, which identifies the action the opener function should perform. The opener can allocate a handle or pointer to contain information such as file reference numbers. This value is passed to the I/O routines in the ioRefNum field of the edition opener parameter block.
  2282. The eoOpen and eoOpenNew edition opener verbs (described in “Calling an Edition Opener” on page 2-64) return a pointer to a function to do the actual reading and writing.
  2283. The following sections describe
  2284. n    how to get the current edition opener 
  2285. n    how to set your own edition opener 
  2286. n    how to call an edition opener 
  2287. n    the edition opener parameters
  2288.  
  2289. Getting the Current Edition Opener
  2290.  
  2291. When you want to get the current edition opener, use the GetEditionOpenerProc function.
  2292. err := GetEditionOpenerProc(opener);
  2293. The opener parameter returns a pointer to the current edition opener. A different current opener is kept for each application. One application’s opener is never called by another application.
  2294.  
  2295. Setting an Edition Opener
  2296.  
  2297. You can provide your own edition opener. To do so, use the SetEditionOpenerProc function.
  2298. err := SetEditionOpenerProc(@MyOpener);
  2299. The @MyOpener parameter is a pointer to the edition opener function that you are providing. If you set the current opener to be a routine in your own code, be sure to call the GetEditionOpenerProc function first so that you can save the previous opener. If your opener is passed a selector that it does not understand, use the previous opener provided by the Edition Manager to handle it. See the next section for a list of selectors.
  2300.  
  2301.  
  2302. Calling an Edition Opener
  2303.  
  2304. You use the CallEditionOpenerProc function to call an edition opener. Since the Edition Manager is a package that may move, a real pointer cannot be safely returned for the standard opener and I/O routines. The system opener and the 
  2305. I/O routines are returned as a value that is not a valid address to a procedure. The CallEditionOpenerProc and CallFormatIOProc functions check for these values and call the system openers.
  2306. You should never assume that a value for a system opener is a fixed constant.
  2307. err := CallEditionOpenerProc (selector, PB, routine);
  2308. Set the selector parameter to one of the edition opener verbs. The edition opener verbs include
  2309. n    eoCanSubscribe
  2310. n    eoOpen
  2311. n    eoClose
  2312. n    eoOpenNew
  2313. n    eoCloseNew
  2314. The PB parameter of the CallEditionOpenerProc function is an edition opener parameter block.
  2315. TYPE EditionOpenerParamBlock = 
  2316.     RECORD
  2317.         info:                    EditionInfoRecord;                            {edition container to }
  2318.                                                         { be subscribed to}
  2319.         sectionH:                    SectionHandle;                            {publisher or }
  2320.                                                         { subscriber }
  2321.                                                         { requesting open}
  2322.         document:                    FSSpecPtr;                            {document passed}
  2323.         fdCreator:                    OSType;                            {Finder creator type}
  2324.         ioRefNum:                    LongInt;                            {reference number}
  2325.         ioProc:                    FormatIOProcPtr;                            {routine to read }
  2326.                                                         { formats}
  2327.         success:                    Boolean;                            {reading or writing }
  2328.                                                         { was successful}
  2329.         formatsMask:                    SignedByte;                            {formats required to }
  2330.                                                         { subscribe}
  2331.     END;
  2332. The routine parameter of the CallEditionOpenerProc function is a pointer to an edition opener function.
  2333. The following list shows which fields of the edition opener parameter block are used by the edition opener verbs:
  2334. Opener verb        Field    Description    Called by (continued)    
  2335. eoCanSubscribe    Æ    info    Edition container to subscribe to.    NewSubscriberDialogfunction for a subscriber    
  2336.     Æ    formatsMask    Formats required to subscribe.        
  2337.     ¨    Return value    A noErr code indicates that an edition container can be subscribed to. A noTypeErr code indicates that an edition container cannot be subscribed to.        
  2338. eoOpen    Æ    info    Edition container to open for reading.    OpenEdition and GetStandardFormats functions for a subscriber    
  2339.     Æ    sectionH    Subscriber section requesting open or NIL.        
  2340.                     
  2341.     ¨    ioRefNum    Reference number for use by I/O routine. Not the same as EditionRefNum.        
  2342.                     
  2343.     ¨    ioProc    I/O routine to call to read formats.        
  2344.     ¨    Return value    A noErr code or appropriate error code.        
  2345. eoClose    Æ    info    Edition container to be closed for reading.    CloseEdition and GetStandardFormats functions for a subscriber    
  2346.                     
  2347.     Æ    sectionH    Subscriber section requesting close or NIL.        
  2348.                     
  2349.     Æ    ioRefNum    Value returned by eoOpen.        
  2350.     Æ    ioProc    Value returned by eoOpen.        
  2351.     Æ    success    Success value passed to the CloseEdition function.        
  2352.                     
  2353.     ¨    Return value    A noErr code or appropriate error code.        
  2354.                 
  2355. continued    
  2356. eoOpenNew    Æ    info    Edition container to open for writing.    OpenNewEdition function for a publisher    
  2357.     Æ    sectionH    Publisher section requesting open or NIL.        
  2358.                     
  2359.     Æ    document    Document pointer passed into the OpenNewEdition function.        
  2360.                     
  2361.     Æ    fdCreator    The fdCreator passed into the OpenNewEdition function.        
  2362.                     
  2363.     ¨    ioRefNum    Reference number for use by I/O routine. Not the same as EditionRefNum.        
  2364.                     
  2365.                     
  2366.     ¨    ioProc    I/O routine to call to write formats.        
  2367.     ¨    Return value    A noErr code or appropriate error code.        
  2368. eoCloseNew    Æ    info    Edition container to be closed after writing.    CloseEdition function for a publisher    
  2369.                     
  2370.     Æ    sectionH    Publisher section requesting close or NIL.        
  2371.                     
  2372.     Æ    ioRefNum    Value returned by eoOpenNew.        
  2373.     Æ    ioProc    Value returned by eoOpenNew.        
  2374.     Æ    success    Success value passed to the CloseEdition function.        
  2375.                     
  2376.     ¨    Return value    A noErr code or appropriate error code.        
  2377.  
  2378. As Listing 2-9 demonstrates, you install your own edition opener function by first saving the current opener and then installing your own opener. The listing also shows an edition opener, the MyEditionOpener function. When it receives the eoCanSubscribe opener verb, the MyEditionOpener function calls another application-defined routine, MyCanSubscribe. The Edition Manager sends your edition opener this verb to help it build the list of files displayed by the NewSubscriber function. The MyCanSubscribe function returns noErr if it can subscribe to the file; otherwise, it calls the original edition opener to handle the request.
  2379.  
  2380. Listing 2-9    
  2381. Using your own edition opener function
  2382.  
  2383. VAR
  2384.     gOriginalOpener: EditionOpenerProcPtr;    {global variable}
  2385.  
  2386. PROCEDURE MyInstallMyOpener;
  2387. BEGIN
  2388.     FailOSErr(GetEditionOpenerProc(gOriginalOpener));
  2389.     FailOSErr(SetEditionOpenerProc(@MyEditionOpener));
  2390. END; {MyInstallMyOpener}
  2391.  
  2392. FUNCTION MyEditionOpener (selector: EditionOpenerVerb; 
  2393.                                   VAR PB: EditionOpenerParamBlock) 
  2394.                                     : OSErr; 
  2395. BEGIN
  2396.     WITH PB DO
  2397.     BEGIN
  2398.         CASE selector OF
  2399.             eoCanSubscribe:
  2400.                 MyEditionOpener := MyCanSubscribe(PB);
  2401.             eoOpen:
  2402.                 MyEditionOpener := MyEditionOpen(PB);
  2403.             eoClose:
  2404.                 MyEditionOpener := MyEditionClose(PB);
  2405.             OTHERWISE
  2406.                 {call the original edition opener}
  2407.                 MyEditionOpener 
  2408.                     := CallEditionOpenerProc(selector, PB,
  2409.                                                     gOriginalOpener);
  2410.         END; {of CASE}
  2411.     END; {of WITH}
  2412. END; {MyEditionOpener}
  2413.  
  2414. FUNCTION MyCanSubscribe (VAR PB: EditionOpenerParamBlock): OSErr;
  2415. BEGIN
  2416.     {check file type to see if it is a file you can emulate as an }
  2417.     { edition}
  2418.     IF PB.info.fdType = {for example}'PICT' THEN
  2419.         MyCanSubscribe := noErr
  2420.     ELSE {otherwise, let the saved edition opener decide}
  2421.             MyCanSubscribe := CallEditionOpenerProc(eoCanSubscribe,
  2422.                                                                 PB, gOriginalOpener);
  2423. END; {MyCanSubscribe}
  2424.  
  2425.  
  2426. Opening and Closing Editions
  2427.  
  2428. Each time the Edition Manager opens or closes an edition container, it calls the current edition opener procedure and passes it an opener verb and a parameter block.
  2429. Your opener must be careful when closing documents since a document may already have been opened by another application. Be sure to use the Open/Deny modes whenever possible. Do not close a document if it was already open when your application opened it.
  2430.  
  2431. Listing Files That Can Be Subscribed To
  2432.  
  2433. The NewSubscriberDialog function calls the edition opener function and passes the eoCanSubscribe opener verb in the selector parameter to build the list of files that can be subscribed to. The preview in the subscriber dialog box is generated by calling the GetStandardFormats function (described in “Edition Container Formats” on page 2-101), which calls the format I/O procedure with the verbs eoOpen, ioHasFormat, ioRead, and then eoClose. See “Calling a Format I/O Function” on this page for detailed information on format I/O verbs.
  2434.  
  2435. Reading From and Writing to Files
  2436.  
  2437. The I/O procedure is a routine that actually reads and writes the data. It too has an interface of a selector and a parameter block.
  2438. To override the standard reading and writing functions, create an I/O function. Note that you also need to provide your own opener function to call your I/O function. See “Calling an Edition Opener” on page 2-64.
  2439. FUNCTION MyIO (selector: FormatIOVerb; 
  2440.                     VAR PB: FormatIOParamBlock): OSErr;
  2441.  
  2442. Calling a Format I/O Function
  2443.  
  2444. To indicate to the Edition Manager which format I/O function to use, use the CallFormatIOProc function.
  2445. err := CallFormatIOProc (selector, PB, routine);
  2446. Set the selector parameter to one of the format I/O verbs. The format I/O verbs include 
  2447. n    ioHasFormat
  2448. n    ioReadFormat
  2449. n    ioNewFormat
  2450. n    ioWriteFormat
  2451. The PB parameter of the CallFormatIOProc function contains a format I/O parameter block.
  2452. TYPE FormatIOParamBlock = 
  2453.     RECORD
  2454.         ioRefNum:                    LongInt;                    {reference number}
  2455.         format:                    FormatType;                    {edition format type}
  2456.         formatIndex    :                LongInt;                    {opener-specific enumeration }
  2457.                                                 { of formats}
  2458.         offset:                    LongInt;                    {offset into format}
  2459.         buffPtr:                    Ptr;                    {data starts here}
  2460.         buffLen:                    LongInt;                    {length of data}
  2461.     END;
  2462. The routine parameter of the CallFormatIOProc function is a pointer to a format
  2463. I/O function.
  2464. The following list shows which fields of FormatIOParamBlock are used by the format I/O verbs:
  2465. Format I/O verb        Parameter    Description    Called by (continued)    
  2466. ioHasFormat    Æ    ioRefNum    I/O reference number returned by opener.    EditionHasFormat, GetStandardFormats, and ReadEdition functions    
  2467.     Æ    format    Check for this format.        
  2468.     ¨    formatIndex    An optional enumeration of the supplied format.        
  2469.     ¨    buffLen    If found, return the length size or –1 if size is unknown.        
  2470.     ¨    Return value    A noErr or noTypeErr code.        
  2471.                 
  2472. continued    
  2473. ioReadFormat    Æ    ioRefNum    I/O reference number returned by opener.    ReadEdition and GetStandardFormats functions    
  2474.     Æ    format    Get this format.        
  2475.     Æ    formatIndex    Value returned by ioHasFormat.        
  2476.     Æ    offset    Read format beginning from this offset.        
  2477.     Æ    buffPtr    Put data beginning here.        
  2478.     ´    buffLen    Specify buffer length to read, and return actual amount received.        
  2479.     ¨    Return value    A noErr code, or appropriate error code.        
  2480. ioNewFormat    Æ    ioRefNum    I/O reference number returned by opener.    SetEditionFormatMarkand WriteEdition functions    
  2481.     Æ    format    Create this format.        
  2482.     ¨    formatIndex    An optional enumeration of the supplied format.        
  2483.     ¨    Return value    A noErr code, or appropriate error code.        
  2484. ioWriteFormat    Æ    ioRefNum    I/O reference number returned by opener.    WriteEdition function    
  2485.     Æ    format    Get this format.        
  2486.     Æ    formatIndex    Value returned by ioNewFormat.        
  2487.     Æ    offset    Write format beginning from this offset.        
  2488.     Æ    buffPtr    Get data beginning here.        
  2489.     ´    buffLen    Specify buffer length to write.        
  2490.     ¨    Return value    A noErr code or appropriate error code.        
  2491.  
  2492. The marks for each format are kept by the Edition Manager. The format I/O function only needs to be able to read or write, beginning at any offset. If you know that your application always reads an entire format sequentially, you can ignore the offset. 
  2493.  
  2494.  
  2495. Edition Manager Reference
  2496.  
  2497. This section describes the data structures and routines that are specific to the Edition Manager. The “Data Structures” section describes the edition container record and the section record. The “Edition Manager Routines” section describes the routines your application can use to implement publish and subscribe features in your application.
  2498.  
  2499. Data Structures
  2500.  
  2501. This section describes the edition container record and the section record. See page 2-91 for a description of the new subscriber reply record, page 2-93 for a description of the new publisher reply record, page 2-95 for a description of the section options record, and page 2-99 for a description of the edition info record. For information on the edition opener parameter block and format I/O parameter block, see page 2-103 and page 2-104, respectively.
  2502.  
  2503. The Edition Container Record
  2504.  
  2505. An edition container record identifies a specific edition file. Many Edition Manager routines require an edition container record as a parameter. The EditionContainerSpec data type defines an edition container record.
  2506. TYPE EditionContainerSpec = 
  2507.     RECORD
  2508.         theFile:                        FSSpec;                    {file containing edition }
  2509.                                                     { data}
  2510.         theFileScript:                        ScriptCode;                    {script code of filename}
  2511.         thePart:                        LongInt;                    {which part of file, }
  2512.                                                     { always kPartsNotUsed}
  2513.         thePartName:                        Str31;                    {reserved}
  2514.         thePartScript:                        ScriptCode;                    {reserved}
  2515.     END;
  2516. Field descriptions
  2517. theFile    A file specificiation record that identifies the name and location of the edition file. Specify the file using the standard conventions for file specification records as described in the chapter “Introduction to File Management” in Inside Macintosh: Files.
  2518.  
  2519. theFileScript    A script code that identifies the script in which the name of the document is to be displayed in the Finder. A script code of smSystemScript represents the default system script.
  2520. thePart    A value that must always be set to kPartsNotUsed in System 7.
  2521. thePartName    Reserved.
  2522. thePartScript    Reserved.
  2523.  
  2524. The Section Record
  2525.  
  2526. A section record identifies a specific publisher or subscriber section. It contains information to identify the section as a publisher or a subscriber, a time stamp to record the last modification of the section, and unique identification for each section. Many Edition Manager routines require a handle to a section record as a parameter. The SectionRecord data type defines a section record.
  2527. TYPE SectionRecord = 
  2528.     RECORD
  2529.         version:                    SignedByte;                    {always 1 in 7.0}
  2530.         kind:                    SectionType;                    {publisher or subscriber}
  2531.         mode:                    UpdateMode;                    {automatic or manual}
  2532.         mdDate:                    TimeStamp;                    {last change in document}
  2533.         sectionID:                    LongInt;                    {application-specific, }
  2534.                                                 { unique per document}
  2535.         refCon:                    LongInt;                    {application-specific}
  2536.         alias:                    AliasHandle;                    {handle to alias record}
  2537.  
  2538.         {The following fields are private and are set up by the }
  2539.         { RegisterSection function. Do not modify the private }
  2540.         { fields.}
  2541.         subPart:                    LongInt;                    {private}
  2542.         nextSection:                    SectionHandle;                    {private, do not use as a }
  2543.                                                 { linked list}
  2544.         controlBlock:                    Handle;                    {may be used for comparison }
  2545.                                                 { only}
  2546.         refNum:                    EditionRefNum;                    {private}
  2547. END;
  2548. Field descriptions
  2549. version    Indicates the version of the section record, currently $01.
  2550.  
  2551. kind    Defines the section type as either publisher or subscriber with the stPublisher or stSubscriber constant.
  2552. mode    Indicates if editions are updated automatically or manually.
  2553. mdDate    Indicates which version (modification date) of the section’s contents is contained within the publisher or subscriber. The mdDate field is set to 0 when you create a new subscriber section and to the current time when you create a new publisher. Be sure to update this field each time publisher data is modified. The section’s modification date is compared to the edition’s modification date to determine whether the section and the edition contain the same data. The section modification date is displayed in the publisher and subscriber options dialog boxes. See “Closing an Edition” on page 2-28 for detailed information.
  2554. sectionID    Provides a unique number for each section within a document. A simple way to implement this is to create a counter for each document that is saved to disk with the document. The counter should start at 1. The section ID is currently used as a tie breaker in the GoToPublisherSection function when there are multiple publishers to the same edition in a single document. The section ID should not be 0 or –1. See “Duplicating Publishers and Subscribers” on page 2-58 for information on multiple publishers.
  2555. refCon    Reference constant available for application-specific use.
  2556. alias    Contains a handle to the alias record for a particular section within a document.
  2557. Whenever the user creates a publisher or subscriber, call the NewSection function (described on page 2-75) to create a section record and alias record.
  2558.  
  2559. Edition Manager Routines
  2560.  
  2561. This section describes the routines you use to
  2562. n    initialize the Edition Manager
  2563. n    create and register a section
  2564. n    create and delete an edition container
  2565. n    set and locate a format mark
  2566. n    read in edition data
  2567. n    write out edition data
  2568. n    close an edition after reading or writing
  2569. n    display dialog boxes
  2570. n    locate a publisher and edition from a subscriber
  2571. n    read and write non-edition files
  2572. Result codes appear at the end of each function where applicable. In addition to the specific result codes listed, you may receive errors generated by the Alias Manager, File Manager, and Memory Manager.
  2573.  
  2574.  
  2575. Initializing the Edition Manager
  2576.  
  2577. You use the InitEditionPack function to initialize the Edition Manager. Note that you should call this function only once.
  2578.  
  2579. InitEditionPack
  2580.  
  2581. Before calling the InitEditionPack function, be sure to determine whether the Edition Manager is available on your system by using the Gestalt function with the gestaltEditionMgrAttr ('edtn') selector.
  2582. FUNCTION InitEditionPack: OSErr;
  2583. DESCRIPTION
  2584. The InitEditionPack function returns an error if the package could not be loaded into the system heap and properly initialized. 
  2585. RESULT CODESnoErr    0    No error    
  2586. memFullErr    –108    Could not load package    
  2587.  
  2588.  
  2589. Creating and Registering a Section
  2590.  
  2591. You use the NewSection function to create a new section (either publisher or subscriber) and alias record (which is a reference to the edition container from the document containing the publisher or subscriber section).
  2592. The NewSection function registers a section much as the RegisterSection function informs the Edition Manager about a section (except that the NewSection function does not resolve an alias to find the edition container).
  2593. When a section needs to be disposed of because the document containing the section is being closed or because the user has canceled the section, you need to call the UnRegisterSection function before disposing of the section.
  2594. Using the IsRegisteredSection function, your application must verify that each event received is for a registered section. This is necessary because your application may have just called UnRegisterSection while the event was already being held in the event queue.
  2595. If a user saves a document that contains sections under another name (using Save As) or pastes a portion of a document that contains a section into another document, use the AssociateSection function to update the section’s alias record. 
  2596.  
  2597.  
  2598. NewSection
  2599.  
  2600. Use the NewSection function to create a new section record and alias record for a new publisher or subscriber.
  2601. FUNCTION NewSection (container: EditionContainerSpec;
  2602.                             sectionDocument: FSSpecPtr; 
  2603.                             kind: SectionType; sectionID: LongInt;
  2604.                             initialMode: UpdateMode; 
  2605.                             VAR sectionH: SectionHandle): OSErr;
  2606. container    The edition you want to publish or subscribe to. 
  2607. sectionDocument
  2608. The volume reference number, directory ID, and filename of the document that contains a section. The sectionDocument parameter can be NIL if your current document has never been saved. If so, when the user finally saves the document, remember to call the AssociateSection function for each section to update its alias record.
  2609. kind    The type of section (publisher or subscriber) being created. 
  2610. sectionID    A unique number for a section within a document. The NewSection function initializes the sectionID field of the new section record with the specified value. Do not use 0 or –1 for an ID number; these numbers are reserved. If your application copies a section, you need to specify a unique number for the copied section. 
  2611. initialMode
  2612. The update mode for the section. For publishers this is either the pumOnSave or pumManual constant, and for subscribers it is either sumAutomatic or sumManual. A subscriber created with sumAutomatic mode automatically receives a Section Read event. To prevent this initial Section Read event, you should set the initialMode parameter to sumManual and then, when NewSection returns, set the mode field of the section record to sumAutomatic.
  2613. sectionH    The NewSection function returns a handle to the allocated section record in this parameter. If an error occurs, NewSection returns NIL in this parameter.
  2614. DESCRIPTION
  2615. The NewSection function allocates two handles in the current zone: one handle for the section record and another handle for the alias record. Note that you are responsible for unregistering handles created by the Edition Manager.
  2616. Your application receives the multiplePublisherWrn result code if there is another registered publisher to the same edition. Your application receives the notThePublisherWrn result code if another publisher (to the same edition) was the last section to write to the edition. The multiplePublisherWrn result code takes priority over the notThePublisherWrn result code.
  2617. RESULT CODESnoErr    0    No error    
  2618. editionMgrInitErr    –450    Manager not initialized    
  2619. badSectionErr    –451    Not a valid section type    
  2620. badSubPartErr    –454    Bad edition container spec    
  2621. multiplePublisherWrn    –460    Already is a publisher    
  2622. notThePublisherWrn    –463    Not the publisher    
  2623.  
  2624. SEE ALSO
  2625. For information on the edition container record, see page 2-71. For information on the section record, see “The Section Record” beginning on page 2-72. For information on file specification records, see Inside Macintosh: Files. See Listing 2-4 on page 2-33 for an example that uses NewSection to create a publisher and Listing 2-6 on page 2-40 for an example that creates a subscriber using NewSection.
  2626.  
  2627. RegisterSection
  2628.  
  2629. When opening a document that contains sections, register each section using the RegisterSection function. 
  2630. FUNCTION RegisterSection (sectionDocument: FSSpec;
  2631.                                   sectionH: SectionHandle; 
  2632.                                   VAR aliasWasUpdated: Boolean): OSErr;
  2633. sectionDocument
  2634. The volume reference number, directory ID, and filename of the document that contains a section. 
  2635. sectionH    A handle to the section record for a given section.
  2636. aliasWasUpdated
  2637. A Boolean value that returns TRUE if the alias for the edition container subscribed to was out of date and was updated. This may occur if the edition file was moved to a new location or was renamed.
  2638. DESCRIPTION
  2639. The RegisterSection function adds the section record to the Edition Manager’s list of registered sections and tries to allocate a control block. After calling the RegisterSection function, the controlBlock field of the section record contains either NIL or a valid control block.
  2640. For a subscriber, the controlBlock field contains NIL if the RegisterSection function could not locate the edition container being subscribed to. The RegisterSection function then returns either the containerNotFoundWrn or the userCanceledErr result code. For a publisher, if the RegisterSection function could not locate its corresponding edition container, the Edition Manager creates an edition container in the last place the edition was located and creates a control block for it. If the RegisterSection function could not locate a publisher’s corresponding edition container or its volume, the controlBlock field contains NIL. You should never re-register a section that is already registered.
  2641. Note that you can compare control blocks for individual sections. If two sections contain the same control block value, these sections publish or subscribe to the same edition (unless the control block is NIL). The Edition Manager keeps track of how many sections are referencing a control block to know when it can be deallocated. The control block maintains a count of how many sections are referencing it. Each time you use the UnRegisterSection function, the control block subtracts 1 from the number of sections. When the number of sections reaches 0, the control block is deallocated.
  2642. Your application receives the multiplePublisherWrn result code if there is another registered publisher to the same edition. Your application receives the notThePublisherWrn result code if another publisher (to the same edition) was the last section to write to the edition. The multiplePublisherWrn result code takes priority over the notThePublisherWrn result code.
  2643. RESULT CODESnoErr    0    No error    
  2644. userCanceledErr    –128    User clicked Cancel in dialog box    
  2645. editionMgrInitErr    –450    Manager not initialized    
  2646. badSectionErr    –451    Not valid section type    
  2647. multiplePublisherWrn    –460    Already is a publisher    
  2648. containerNotFoundWrn    –461    Alias was not resolved    
  2649. notThePublisherWrn    –463    Not the publisher    
  2650.  
  2651. SEE ALSO
  2652. For information on the section record, see “The Section Record” beginning on page 2-72. For information on file specification records, see Inside Macintosh: Files. For additional information and an example of the use of RegisterSection, see “Opening and Closing a Document Containing Sections” beginning on page 2-22.
  2653.  
  2654. UnRegisterSection
  2655.  
  2656. When a section needs to be disposed of because the document containing the section is being closed or because the user has canceled the section, you need to call the UnRegisterSection function before disposing of the section.
  2657. FUNCTION UnRegisterSection (sectionH: SectionHandle): OSErr;
  2658. sectionH    A handle to the section record for a given section.
  2659. DESCRIPTION
  2660. The UnRegisterSection function removes the section from the Edition Manager’s list of registered sections. You can then dispose of the section record and alias record with standard Memory Manager and Resource Manager calls. Once unregistered, a section does not receive any events and cannot read or write any data. Depending on your Clipboard strategy, you may want to unregister sections that have been cut into the Clipboard.
  2661. RESULT CODESnoErr    0    No error    
  2662. fBsyErr    –47    Section doing I/O    
  2663. editionMgrInitErr    –450    Manager not initialized    
  2664. notRegisteredSectionErr    –452    Not registered    
  2665.  
  2666.  
  2667. IsRegisteredSection
  2668.  
  2669. Upon receiving a section event, your application must call the IsRegisteredSection function to verify that the event received is for a registered section. You must call IsRegisteredSection before handling a section event because your application may have just called UnRegisterSection while the event was already being held in the event queue.
  2670. FUNCTION IsRegisteredSection (sectionH: SectionHandle): OSErr;
  2671. sectionH    A handle to the section record for a given section. 
  2672. DESCRIPTION
  2673. The IsRegisteredSection function returns a result code (not a Boolean value) indicating whether the section is registered. A noErr result code indicates that a section is registered.
  2674. RESULT CODESnoErr    0    No error    
  2675. notRegisteredSectionErr    –452    Not registered    
  2676.  
  2677. SEE ALSO
  2678. For an example of the use of IsRegisteredSection, see Listing 2-1 on page 2-14.
  2679.  
  2680.  
  2681. AssociateSection
  2682.  
  2683. If a user saves a document that contains sections under another name (using Save As) or pastes a portion of a document that contains a section into another document, use the AssociateSection function to update the section’s alias record.
  2684. FUNCTION AssociateSection (sectionH: SectionHandle;
  2685.                                     newSectionDocument: FSSpecPtr): OSErr;
  2686. sectionH    A handle to the section record for a given section. 
  2687. newSectionDocument
  2688. The volume reference number, directory ID, and filename of the new document. 
  2689. DESCRIPTION
  2690. The AssociateSection function calls UpdateAlias on the section’s alias record. 
  2691. RESULT CODESnoErr    0    No error    
  2692. paramErr    –50    Invalid parameter    
  2693.  
  2694. SEE ALSO
  2695. For information on the UpdateAlias function, see the chapter “Alias Manager” in Inside Macintosh: Files.
  2696.  
  2697. Creating and Deleting an Edition Container
  2698.  
  2699. Each time a user creates a new publisher section within a document to an edition that does not already exist, you use the CreateEditionContainerFile function to create an empty edition container.
  2700. To remove the edition container, use the DeleteEditionContainerFile function.
  2701.  
  2702. CreateEditionContainerFile
  2703.  
  2704. You use the CreateEditionContainerFile function to create an empty edition container.
  2705. FUNCTION CreateEditionContainerFile 
  2706.                             (editionFile: FSSpec; fdCreator: OSType; 
  2707.                              editionFileNameScript: ScriptCode): OSErr;
  2708. editionFile
  2709. The volume reference number, directory ID, and filename for the edition container being created. 
  2710. fdCreator    The creator type for the edition.
  2711. editionFileNameScript
  2712. The script of the filename. (You can get this value from the theFileScript field of an edition container specification record.)
  2713. DESCRIPTION
  2714. The CreateEditionContainerFile function creates an empty edition container file (it does not contain any formats). This function sets the file type of the edition to 'edtu'. As soon as you write data to the edition, the Edition Manager updates the type (to 'edtp' for graphics, 'edtt' for text, or 'edts' for sound). If your application writes both 'TEXT' and 'PICT' formats to the edition, the Edition Manager sets the file type to the type that was written first. If your application has a bundle, you should designate an icon for the appropriate edition types that you can write. 
  2715. RESULT CODESnoErr    0    No error    
  2716. dskFulErr    –34    Disk is full    
  2717. nsvErr    –35    No such volume    
  2718. ioErr    –36    I/O error    
  2719. bdNamErr    –37    Bad filename    
  2720. fnfErr    –43    File not found    
  2721. dirNFErr    –120    Directory not found    
  2722. editionMgrInitErr    –450    Manager not initialized    
  2723.  
  2724. SEE ALSO
  2725. For information on file specification records, see Inside Macintosh: Files. For an example of the use of CreateEditionContainerFile, see Listing 2-4 on page 2-33.
  2726.  
  2727. DeleteEditionContainerFile
  2728.  
  2729. If a user cancels a publisher section within a document or closes a document containing a newly created publisher without saving, you need to remove the edition container. 
  2730. To locate the appropriate edition container to be deleted, use the GetEditionInfo function. You use the UnRegisterSection function (only after using the GetEditionInfo function) to unregister the section record and alias record of the publisher being canceled. 
  2731. To remove the edition container, use the DeleteEditionContainerFile function. 
  2732. FUNCTION DeleteEditionContainerFile (editionFile: FSSpec): OSErr;
  2733. editionFile
  2734. The volume reference number, directory ID, and filename for the edition container being deleted.
  2735. DESCRIPTION
  2736. If the user cancels a publisher, do not call the DeleteEditionContainerFile function until the user saves the document. This allows the user to undo changes and revert to the last saved version of the document.
  2737. The DeleteEditionContainerFile function deletes the edition container only if there is no registered publisher. You need to unregister a publisher before you can delete its corresponding edition container.
  2738. You should use the DeleteEditionContainerFile function even if there are subscribers to the edition. When a subscriber section tries to read in data, it receives an error if the edition container has been deleted. 
  2739. RESULT CODESnoErr    0    No error    
  2740. nsvErr    –35    No such volume    
  2741. ioErr    –36    I/O error    
  2742. bdNamErr    –37    Bad filename    
  2743. fnfErr    –43        File not found    
  2744. dirNFErr    –120    Directory not found    
  2745. editionMgrInitErr    –450    Manager not initialized    
  2746.  
  2747. SEE ALSO
  2748. See page 2-98 for detailed information on the GetEditionInfo function. See page 2-77 for information on the UnRegisterSection function. For information on file specification records, see Inside Macintosh: Files. 
  2749.  
  2750. Setting and Getting a Format Mark
  2751.  
  2752. Use the SetEditionFormatMark function to set the current mark for a section format and the GetEditionFormatMark function to get the current mark for a particular format. 
  2753.  
  2754.  
  2755. SetEditionFormatMark
  2756.  
  2757. A format mark indicates the next position of a read or write operation. Initially, a mark defaults to 0. After reading or writing data, the format mark is set past the last position written to or read from. To set the current mark for a given format, use the SetEditionFormatMark function.
  2758. FUNCTION SetEditionFormatMark (whichEdition: EditionRefNum;
  2759.                                          whichFormat: FormatType;
  2760.                                          setMarkTo: LongInt): OSErr;
  2761. whichEdition
  2762. The reference number for the edition. 
  2763. whichFormat
  2764. The format type for the edition.
  2765. setMarkTo    The offset for the next read or write for this format.
  2766. DESCRIPTION
  2767. The SetEditionFormatMark function sets the current mark for the specified format type according to the value of the setMarkTo parameter.
  2768. RESULT CODESnoErr    0    No error    
  2769. rfNumErr    –51    Bad edition reference number    
  2770. noTypeErr    –102    Unknown format (subscriber only)    
  2771. editionMgrInitErr    –450    Manager not initialized    
  2772.  
  2773.  
  2774. GetEditionFormatMark
  2775.  
  2776. Use the GetEditionFormatMark function to get the current mark for a particular format.
  2777. FUNCTION GetEditionFormatMark (whichEdition: EditionRefNum;
  2778.                                          whichFormat: FormatType; 
  2779.                                          VAR currentMark: LongInt): OSErr;
  2780. whichEdition
  2781. The reference number for the edition. 
  2782. whichFormat
  2783. The format type whose mark you want to get.
  2784. currentMark
  2785. The GetEditionFormatMark function returns the mark for the specified format in this parameter. 
  2786. DESCRIPTION
  2787. If the edition does not support the format specified in the whichFormat parameter, you receive a noTypeErr result code.
  2788. RESULT CODESnoErr    0    No error    
  2789. rfNumErr    –51    Bad edition reference number    
  2790. noTypeErr    –102    Unknown format    
  2791. editionMgrInitErr    –450    Manager not initialized    
  2792.  
  2793.  
  2794. Reading in Edition Data
  2795.  
  2796. To initiate the reading of data from an edition (for a subscriber), use the OpenEdition function.
  2797. Use the EditionHasFormat function to learn in which formats the edition data is available.
  2798. Use the ReadEdition function to read data from an edition. This function reads from the current mark for the specified format.
  2799.  
  2800. OpenEdition
  2801.  
  2802. To initiate the reading of data from an edition (for a subscriber), use the OpenEdition function.
  2803. FUNCTION OpenEdition (subscriberSectionH: SectionHandle; 
  2804.                              VAR refNum: EditionRefNum): OSErr;
  2805. subscriberSectionH
  2806. A handle to the section record for a given section. 
  2807. refNum    The OpenEdition function returns the reference number for the edition in this parameter.
  2808. DESCRIPTION
  2809. The OpenEdition function opens an edition for reading and returns a reference number that your application can use to refer to this edition in other Edition Manager routines. Multiple subscribers can each call the OpenEdition function simultaneously (each call returns a different reference number) and read data from a single edition. If a publisher (located on a different machine) is writing to an edition when you use the OpenEdition function, you receive an flLckedErr result code.
  2810. RESULT CODESnoErr    0    No error    
  2811. fnfErr    –43    File not found    
  2812. flLckedErr    –45    Publisher writing to an edition    
  2813. permErr    –54    Not a subscriber    
  2814. editionMgrInitErr    –450    Manager not initialized    
  2815.  
  2816. SEE ALSO
  2817. For an example of the use of OpenEdition, see Listing 2-7 on page 2-42.
  2818.  
  2819. EditionHasFormat
  2820.  
  2821. Use the EditionHasFormat function to learn in which formats the edition data is available.
  2822. FUNCTION EditionHasFormat (whichEdition: EditionRefNum;
  2823.                                     whichFormat: FormatType; 
  2824.                                     VAR formatSize: Size): OSErr;
  2825. whichEdition
  2826. The reference number for the edition. 
  2827. whichFormat
  2828. The format type that you are requesting. For the whichFormat parameter, you should decide which formats to read in the same way that you do when reading data from the scrap. You can also get a list of all the available formats and their respective lengths by reading the kFormatListFormat ('fmts') format. 
  2829. formatSize
  2830. The EditionHasFormat function returns the format length in this parameter.
  2831. DESCRIPTION
  2832. If the requested format is available, the EditionHasFormat function returns noErr, and the formatSize parameter returns the size of the data in the specified format or kFormatLengthUnknown (–1), which signifies that the size is unknown. You should therefore continue to read the format until there is no more data.
  2833. Note
  2834. Note
  2835. The Translation Manager (if it is available) attempts implicit translation under certain circumstances. For instance, it does so when your application attempts to read from an edition a format type that is not in the edition. In this case, the Translation Manager attempts to translate the data into the requested format. For more information, see the chapter “Translation Manager” in Inside Macintosh: More Macintosh Toolbox.u
  2836.  
  2837. RESULT CODESnoErr    0    No error    
  2838. rfNumErr    –51    Bad edition reference number    
  2839. noTypeErr    –102    Format not available    
  2840. editionMgrInitErr    –450    Manager not initialized    
  2841.  
  2842. SEE ALSO
  2843. For an example of the use of EditionHasFormat, see Listing 2-7 beginning on page 2-42. For information about the Translation Manager and Scrap Manager, see Inside Macintosh: More Macintosh Toolbox.
  2844.  
  2845. ReadEdition
  2846.  
  2847. Use the ReadEdition function to read data from an edition. This function reads from the current mark for the specified format.
  2848. FUNCTION ReadEdition (whichEdition: EditionRefNum; 
  2849.                              whichFormat: FormatType; buffPtr: UNIV Ptr;
  2850.                              VAR buffLen: Size): OSErr;
  2851. whichEdition
  2852. The reference number for the edition. 
  2853. whichFormat
  2854. The format type that you want to read. 
  2855. buffPtr    A pointer to the buffer into which you want to read the data.
  2856. buffLen    The number of bytes that you want to read into the buffer. The ReadEdition function returns the actual number of bytes read in the buffLen parameter. 
  2857. DESCRIPTION
  2858. The ReadEdition function reads data from the edition into the specified buffer. ReadEdition returns in the buffLen parameter the total number of bytes read into the buffer. If the buffLen parameter returns a value smaller than the value you have specified, there is no additional data to read, and the ReadEdition function returns a noErr result code. If you use the ReadEdition function after all data is read in, the ReadEdition function returns an eofErr result code.
  2859. You can read data from an edition while a publisher on the same machine is writing data to the same edition. The data that you are reading is the old edition (not the data that the publisher is writing). If the publisher finishes writing data before you are through reading the old edition data, the ReadEdition function returns an abortErr result code. If the ReadEdition function returns an abortErr result code, you should stop trying to read data and use the CloseEdition function with the successful parameter set to FALSE. 
  2860. Note
  2861. The Translation Manager (if it is available) attempts implicit translation under certain circumstances. For instance, it does so when your application attempts to read from an edition a format type that is not in the edition. In this case, the Translation Manager attempts to translate the data into the requested format. For more information, see the chapter “Translation Manager” in Inside Macintosh: More Macintosh Toolbox.u 
  2862.  
  2863. RESULT CODESnoErr    0    No error    
  2864. abortErr    –27    Publisher has written a new edition    
  2865. ioErr    –36    I/O error    
  2866. fnOpnErr    –38    File not open    
  2867. eofErr    –39    No more data of that format    
  2868. rfNumErr    –51    Bad edition reference number    
  2869. noTypeErr    –102    Format not available    
  2870. editionMgrInitErr    –450    Manager not initialized    
  2871.  
  2872. SEE ALSO
  2873. For an example of the use of ReadEdition, see Listing 2-7 beginning on page 2-42. 
  2874.  
  2875. Writing out Edition Data
  2876.  
  2877. To initiate the writing of data from a publisher to its edition container, use the OpenNewEdition function. (To create an edition container, use the CreateEditionContainerFile function, as described on page 2-79.)
  2878. Use the WriteEdition function to write data to an edition.
  2879.  
  2880.  
  2881. OpenNewEdition
  2882.  
  2883. To initiate the writing of data from a publisher to its edition container, use the OpenNewEdition function.
  2884. FUNCTION OpenNewEdition (publisherSectionH: SectionHandle;
  2885.                                  fdCreator: OSType;
  2886.                                  publisherSectionDocument: FSSpecPtr; 
  2887.                                  VAR refNum: EditionRefNum): OSErr;
  2888. publisherSectionH
  2889. The publisher section that is writing to the edition. 
  2890. fdCreator    The Finder creator type of the new edition icon.
  2891. publisherSectionDocument
  2892. The document that contains the publisher. This parameter is used to create an alias from the edition to the publisher’s document. If you pass NIL for publisherSectionDocument, an alias is not made in the edition file.
  2893. refNum    The OpenNewEdition function returns the reference number for the edition in this parameter. You specify this reference number as a parameter for subsequent calls to WriteEdition, SetEditionFormatMark, and CloseEdition to specify which publisher is writing its data to an edition. If the edition cannot be opened for writing because there is another publisher writing to it, or because the file system does not allow writing, an error is returned and OpenNewEdition sets refNum to NIL. 
  2894. DESCRIPTION
  2895. The OpenNewEdition function opens an edition for writing. The function returns an flLckdErr result code if there is a subscriber on another machine reading data from the same edition. The OpenNewEdition function returns a permErr result code if there is a registered publisher to that edition on another machine.
  2896. The Edition Manager allows two registered publishers that are located on the same machine to write to the same edition. Note that multiple publishers cannot write to the same edition simultaneously—only one publisher can write to an edition at a given time.
  2897. RESULT CODESnoErr    0    No error    
  2898. ioErr    –36    I/O error    
  2899. flLckdErr    –45    Edition in use by another section    
  2900. permErr    –54    Registered publisher on another machine    
  2901. wrPermErr    –61    Not a publisher    
  2902. editionMgrInitErr    –450    Manager not initialized    
  2903.  
  2904. SEE ALSO
  2905. For an example of the use of OpenNewEdition, see Listing 2-5 beginning on 
  2906. page 2-36. 
  2907.  
  2908. WriteEdition
  2909.  
  2910. Use the WriteEdition function to write data to an edition. This function begins writing at the current mark for the specified format.
  2911. FUNCTION WriteEdition (whichEdition: EditionRefNum; 
  2912.                               whichFormat: FormatType; 
  2913.                               buffPtr: UNIV Ptr; buffLen: Size): OSErr;
  2914. whichEdition
  2915. The reference number for the edition. 
  2916. whichFormat
  2917. The format type that you want to write. 
  2918. buffPtr    A pointer to the buffer containing the data to write to the edition. 
  2919. buffLen    The number of bytes that you want to write to the edition. 
  2920. DESCRIPTION
  2921. The WriteEdition function writes the specified number of bytes to the edition. If the data cannot be entirely written to the edition, the WriteEdition function returns an error.
  2922. RESULT CODESnoErr    0    No error    
  2923. dskFulErr    –34    Disk is full    
  2924. ioErr    –36    I/O error    
  2925. rfNumErr    –51    Bad edition reference number    
  2926. editionMgrInitErr    –450    Manager not initialized    
  2927.  
  2928. SEE ALSO
  2929. For an example that writes data to an edition, see Listing 2-5 beginning on page 2-36. 
  2930.  
  2931. Closing an Edition After Reading or Writing
  2932.  
  2933. After finishing reading from or writing to an edition, use the CloseEdition function to close the edition.
  2934.  
  2935.  
  2936. CloseEdition
  2937.  
  2938. Use the CloseEdition function to close an edition after you finish reading from or writing to it.
  2939. FUNCTION CloseEdition (whichEdition: EditionRefNum; 
  2940.                               successful: Boolean): OSErr;
  2941. whichEdition
  2942. The reference number for the edition. 
  2943. successful
  2944. A value that indicates whether your application was successful (TRUE) or unsuccessful (FALSE) in reading from or writing data to the edition.
  2945. DESCRIPTION
  2946. When a subscriber successfully finishes reading data from the edition, the CloseEdition function takes the modification date of the edition file that you have read and puts it in the mdDate field of the subscriber’s section record. This indicates that the data contained in the edition and the subscriber section within the document are the same.
  2947. When a subscriber is unsuccessful in reading data from an edition (because there is not enough memory, or you didn’t find a format that you can read), set the successful parameter to FALSE. The CloseEdition function then closes the edition, but does not set the mdDate field. This implies that the subscriber is not updated with the latest edition.
  2948. When a publisher successfully finishes writing data to an edition, the CloseEdition function makes the data that the publisher has written to the edition available to any subscribers and sets the corresponding edition file’s modification date (ioFlMdDat) to the mdDate field of the publisher’s section record. The Edition Manager then sends a Section Read event to all current subscribers set to automatic update mode. At this point, the file type of the edition file is set based on the first known format that the publisher wrote.
  2949. When a publisher is unsuccessful in writing data to an edition, the CloseEdition function discards what the publisher has written to the edition. The data contained in the edition prior to writing remains unchanged, and Section Read events are not sent to subscribers. 
  2950. RESULT CODESnoErr    0    No error    
  2951. ioErr    –36    I/O error    
  2952. fnOpnErr    –38    File not open    
  2953. rfNumErr    –51    Bad edition reference number    
  2954. editionMgrInitErr    –450    Manager not initialized    
  2955.  
  2956. SEE ALSO
  2957. For an example of the use of CloseEdition, see Listing 2-5 beginning on 
  2958. page 2-36. 
  2959.  
  2960. Displaying Dialog Boxes
  2961.  
  2962. The Edition Manager supports three dialog boxes: publisher, subscriber, and options dialog boxes. Your application can display simple dialog boxes that appear centered on the user’s screen, or you can customize your dialog boxes.
  2963. Use the GetLastEditionContainerUsed function to get the default edition to display.
  2964. Use the NewSubscriberDialog function to display the subscriber dialog box on the user’s screen and use the NewPublisherDialog function to display the publisher dialog box on the user’s screen. Unlike the Standard File Package routines, the NewPublisherDialog and the NewSubscriberDialog functions allow you to specify the initial volume reference number and directory ID so that there can be one default location for editions for all applications.
  2965. You use the SectionOptionsDialog function to display the publisher options and subscriber options dialog boxes on the user’s screen.
  2966. The NewSubscriberExpDialog, NewPublisherExpDialog, and SectionOptionsExpDialog functions are the same as the simple dialog functions but have five additional parameters.
  2967.  
  2968. GetLastEditionContainerUsed
  2969.  
  2970. Use the GetLastEditionContainerUsed function to get the default edition to display. This function allows a user to easily subscribe to the data recently published. 
  2971. FUNCTION GetLastEditionContainerUsed 
  2972.                         (VAR container: EditionContainerSpec): OSErr;
  2973. container    If the GetLastEditionContainerUsed function locates the last edition for which a section was created, the container parameter contains its volume reference number, directory ID, filename, and part, and returns a noErr result code. (The last edition created is associated with the last time that your application or another application located on the same machine used the NewSection function.) 
  2974. DESCRIPTION
  2975. If the last edition used is missing, the GetLastEditionContainerUsed function returns an fnfErr result code, but still returns the correct volume reference number and directory ID that you should use for the NewSubscriberDialog function.
  2976. Pass the information from the GetLastEditionContainerUsed function to the NewSubscriberDialog function.
  2977. RESULT CODESnoErr    0    No error    
  2978. fnfErr    –43    Edition container not found    
  2979. editionMgrInitErr    –450    Manager not initialized    
  2980.  
  2981. SEE ALSO
  2982. For an example of the use of GetLastEditionContainerUsed, see Listing 2-6 beginning on page 2-40. For a description of the edition container record, see page 2-71. The NewSubscriberDialog function is described next.
  2983.  
  2984. NewSubscriberDialog
  2985.  
  2986. When a user chooses the Subscribe To menu command, your application should call the NewSubscriberDialog function to allow the user to choose an edition to subscribe to. 
  2987. FUNCTION NewSubscriberDialog 
  2988.                             (VAR reply: NewSubscriberReply): OSErr;
  2989. reply    The new subscriber reply record. You specify a location to use as the default edition container in the container field of this record. You also specify in the formatsMask field which edition format types NewSubscriberDialog should display. The NewSubscriberDialog function returns information concerning the user’s choice in the canceled and container fields of this record.
  2990. TYPE NewSubscriberReply = 
  2991.     RECORD
  2992.         canceled:                    Boolean;                            {user canceled }
  2993.                                                         { dialog box}
  2994.         formatsMask:                    SignedByte;                            {formats required}
  2995.         container:                    EditionContainerSpec;                            {edition selected}
  2996.     END;
  2997. Field descriptions
  2998. canceled    The NewSubscriberDialog function returns in this field a value that indicates whether the user canceled the dialog box. The function returns TRUE in the canceled field if the user canceled the dialog box. Otherwise, the function returns FALSE in this field and returns in the container field the edition container for the new subscriber.
  2999.  
  3000. formatsMask    The formatsMask field indicates which edition format type (text, graphics, and sound) to display within the subscriber dialog box. You can set the formatsMask field to the following constants: kTEXTformatMask (1), kPICTformatMask (2), or ksndFormatMask (4). To support a combination of formats, add the constants together. For example, a formatsMask of 3 displays both graphics and text edition format types in the subscriber   dialog box.
  3001. container    The edition container of the last edition published or subscribed to. You provide in this parameter the location and filename to use as the default edition to subscribe to. If the user clicks the Subscribe button, NewSubscriberDialog returns FALSE in the canceled field and returns the selected edition container for the new subscriber in the container field. 
  3002.     DESCRIPTION
  3003. The NewSubscriberDialog function displays the subscriber dialog box on the user’s screen. The NewSubscriberDialog function (which is based on the CustomGetFile procedure described in the chapter “Standard File Package” in Inside Macintosh: Files) switches to the volume reference number and directory ID and selects the filename of the edition container that you specified in the container field of the reply parameter. Use the GetLastEditionContainerUsed function to get the edition container of the last edition that was either published or subscribed to, then set the container field to this edition container. This allows the user to publish and then easily subscribe.
  3004. Note that if an edition does not contain either 'PICT', 'TEXT', or 'snd ' data, the NewSubscriberDialog function does not list the edition file in the new subscriber dialog box (unless you install an opener that can recognize the edition’s data in response to the eoCanSubscribe verb).
  3005. RESULT CODESnoErr    0    No error    
  3006. editionMgrInitErr    –450    Manager not initialized or could not load package    
  3007. badSubPartErr    –454    Bad edition container spec    
  3008.  
  3009. SEE ALSO
  3010. For an illustration of the new subscriber dialog box, see Figure 2-12 on page 2-37. For an example of the use of NewSubscriberDialog, see Listing 2-6 beginning on page 2-40. For a description of the edition container record, see page 2-71. For information on edition openers, see “Subscribing to Non-Edition Files” beginning on page 2-62. 
  3011.  
  3012.  
  3013. NewPublisherDialog
  3014.  
  3015. When a user selects a portion of a document and then chooses the Create Publisher menu command, your application should call the NewPublisherDialog function to allow the user to choose a name and location of the edition to which your application writes the publisher data. Your application specifies a location and name to use as the default edition and provides a preview of the publisher data to the NewPublisherDialog function. 
  3016. FUNCTION NewPublisherDialog 
  3017.                         (VAR reply: NewPublisherReply): OSErr;
  3018. reply    A new publisher reply record. You specify a location to use as the default edition container in the container field of this record. You also specify information in the usePart, preview, and previewFormat fields. The NewPublisherDialog function returns information concerning the user’s choice in the canceled, replacing, and container fields of this record.
  3019. TYPE NewPublisherReply = 
  3020.     RECORD
  3021.         canceled:                    Boolean;                    {user canceled dialog box}    
  3022.         replacing:                    Boolean;                    {user chose existing } 
  3023.                                                 { filename for an edition}
  3024.         usePart:                    Boolean;                    {always false in version 7.0}
  3025.         preview:                    Handle;                    {handle to 'prvw', 'PICT', }
  3026.                                                 { 'TEXT', or 'snd ' data} 
  3027.         previewFormat:                    FormatType;                    {type of preview}
  3028.         container:                    EditionContainerSpec;
  3029.                                                 {edition chosen}
  3030.     END;
  3031. Field descriptions
  3032. canceled    The NewPublisherDialog function returns in this field a value that indicates whether the user canceled the dialog box. The function returns TRUE in the canceled field if the user canceled the dialog box. The function returns FALSE in this field if the user clicked the Publish button and returns in the container field the edition container for the new publisher.
  3033.  
  3034. replacing    The NewPublisherDialog function returns TRUE in the replacing field if the user chose an existing filename from the list of available editions and confirmed this replacement. If the value of the replacing field is TRUE, do not call the CreateEditionContainerFile function. If the value of this field and the canceled field is FALSE, you can call CreateEditionContainerFile to create a new edition container.
  3035. usePart    A value that must be set to FALSE before calling the NewPublisherDialog function.
  3036. preview    A handle to 'prvw', 'PICT', 'TEXT', or 'snd ' data. The NewPublisherDialog function displays this data in the preview area of the dialog box.
  3037. previewFormat    A value that indicates which type of data the handle in the preview field references.
  3038. container    An edition container record that specifies the volume reference number, directory ID, and filename to use as the default edition to publish the data to. The NewPublisherDialog function returns in this field the edition container that the user selected. 
  3039. DESCRIPTION
  3040. The NewPublisherDialog function displays the new publisher dialog box on the user’s screen. The NewPublisherDialog function (which is based on the CustomPutFile procedure described in the chapter “Standard File Package” in Inside Macintosh: Files) switches to the volume reference number and directory ID specified by the edition container, sets the editable text item to the filename specified by the edition container, and displays a preview of the publisher data in the new publisher dialog box. The NewPublisherDialog function handles all user interaction until the user clicks the Cancel or Publish button.
  3041. You should deallocate the handle referenced by the preview field to free up memory.
  3042. RESULT CODESnoErr    0    No error    
  3043. editionMgrInitErr    –450    Manager not initialized or could not load package    
  3044. badSubPartErr    –454    Bad edition container spec    
  3045.  
  3046. SEE ALSO
  3047. For an illustration of the new publisher dialog box, see Figure 2-11 on page 2-29. For an example of the use of NewPublisherDialog, see Listing 2-4 beginning on page 2-33. For a description of the edition container record, see page 2-71. 
  3048.  
  3049. SectionOptionsDialog
  3050.  
  3051. Use the SectionOptionsDialog function to display the publisher options and subscriber options dialog boxes on the user’s screen.
  3052. FUNCTION SectionOptionsDialog  
  3053.                             (VAR reply: SectionOptionsReply): OSErr;
  3054. reply    The reply parameter contains a section options reply record. You specify a handle to the publisher’s or subscriber’s section record in the sectionH field of this record. The SectionOptionsDialog function returns information concerning the user’s actions in the canceled, changed, and action fields.
  3055. TYPE SectionOptionsReply = 
  3056.     RECORD
  3057.         canceled:                Boolean;                        {user canceled dialog box}
  3058.         changed:                Boolean;                        {changed the section record}
  3059.         sectionH:                SectionHandle;                        {handle to the specified }
  3060.                                                 { section record}
  3061.         action:                ResType;                        {action codes}
  3062.     END;
  3063. Field descriptions
  3064. canceled    The SectionOptionsDialog function returns in this field a value that indicates whether the user canceled the dialog box. The function returns TRUE in the canceled field if the user canceled the dialog box. Otherwise, the function returns FALSE in this field. 
  3065.  
  3066. changed    The SectionOptionsDialog function returns TRUE in this field if the user changed the section record. For example, the update mode may have changed. Otherwise, the function returns FALSE in this field. 
  3067. sectionH    A handle to the section record for the section the user selected.
  3068. action    The SectionOptionsDialog function returns in this field the code for one of five user actions: action code 'read' for user selection of the Get Edition Now button, action code 'writ' for user selection of the Send Edition Now button, action code 'goto' for user selection of the Open Publisher button, action code 'cncl' for user selection of the Cancel Publisher or Cancel Subscriber button, or action code '    ' ($20202020) for user selection of the OK button.
  3069. DESCRIPTION
  3070. The SectionOptionsDialog function displays the appropriate options dialog box for the specified section record. The function displays information about the subscriber or publisher, such as its latest edition and current update mode setting, and allows the user to perform various actions. The SectionOptionsDialog function handles all user interaction until the user selects a button. The function returns the user’s action in the action field of the reply parameter; your application should then perform the corresponding action. 
  3071. RESULT CODESnoErr    0    No error    
  3072. memFullErr    –108    Memory full    
  3073.  
  3074. SEE ALSO
  3075. For illustrations of the section options dialog box, see Figure 2-13 through Figure 2-16 beginning on page 2-43. For an example of the use of SectionOptionsDialog, see Listing 2-8 beginning on page 2-46. For a description of the section record, see page 2-72. 
  3076.  
  3077. NewSubscriberExpDialog, NewPublisherExpDialog, SectionOptionsExpDialog
  3078.  
  3079. The NewSubscriberExpDialog, NewPublisherExpDialog, and SectionOptionsExpDialog functions are the same as the simple dialog functions but have five additional parameters. These additional parameters allow you to add items to the bottom of the dialog boxes, apply alternate mapping of events to item hits, apply alternate meanings to the item hits, and choose the location of the dialog boxes.
  3080. FUNCTION NewSubscriberExpDialog 
  3081.                     (VAR reply: NewSubscriberReply; where: Point;
  3082.                      expansionDITLresID: Integer; 
  3083.                      dlgHook: ExpDlgHookProcPtr; 
  3084.                      filterProc: ExpModalFilterProcPtr; 
  3085.                      yourDataPtr: UNIV Ptr): OSErr;
  3086. FUNCTION NewPublisherExpDialog 
  3087.                     (VAR reply: NewPublisherReply; where: Point;
  3088.                      expansionDITLresID: Integer; 
  3089.                      dlgHook: ExpDlgHookProcPtr; 
  3090.                      filterProc: ExpModalFilterProcPtr; 
  3091.                      yourDataPtr: UNIV Ptr): OSErr;
  3092. FUNCTION SectionOptionsExpDialog 
  3093.                     (VAR reply: SectionOptionsReply; where: Point;
  3094.                      expansionDITLresID: Integer; 
  3095.                      dlgHook: ExpDlgHookProcPtr; 
  3096.                      filterProc: ExpModalFilterProcPtr; 
  3097.                      yourDataPtr: UNIV Ptr): OSErr;
  3098. reply    A new subscriber reply, new publisher reply, or section options reply record. You specify information in the fields of this record just as you do in the the corresponding fields of records used by NewSubscriberDialog, NewPublisherDialog, and SectionOptionsDialog.
  3099. where    A point that specifies a location on the screen where the function displays the dialog box. You can automatically center the dialog box by passing (–1, –1) in the where parameter. 
  3100. expansionDITLresID
  3101. A value of 0 or a valid item list ('DITL') resource ID. This integer is the ID of a dialog item list whose items are appended to the end of the standard dialog item list. The dialog items keep their relative positions, but they are moved as a group to the bottom of the dialog box.
  3102. dlgHook    A pointer to an expandable dialog hook function or NIL. An expandable dialog hook function is similar to a dialog hook function except that an expandable dialog hook function accepts an additional parameter. The NewSubscriberExpDialog, NewPublisherExpDialog, and SectionOptionsExpDialog functions call your expandable dialog hook function after each call to the ModalDialog procedure. The expandable dialog hook function should take the appropriate action, such as filling in a checkbox. The itemOffset parameter to the expandable dialog hook function is the number of items in the item list before your expansion dialog items. You need to subtract the item offset from the item hit to get the relative item number in the expansion item list. The expandable dialog hook function should return as its function result the absolute item number. 
  3103. filterProc
  3104. A pointer to an expandable modal-dialog filter function or NIL. An expandable modal-dialog filter function is similar to a modal-dialog filter function or event filter function except that an expandable modal-dialog filter function accepts two extra parameters. The ModalDialog procedure calls the expandable modal-dialog filter function you provide in this parameter. An expandable modal-dialog filter function allows you to map real events (such as a mouse-down event) to an item hit (such as clicking a Cancel button). For instance, you may want to map a keyboard equivalent to an item hit.
  3105. yourDataPtr
  3106. Reserved for your use. It is passed back to your hook and event filter function. This parameter does not have to be of type Ptr—it can be any 32-bit quantity that you want. In Pascal, you can pass yourDataPtr in register A6, and declare your dialog hook and event filter as local functions without the last parameter. The stack frame is set up properly for these functions to access their parent local variables.
  3107. DESCRIPTION
  3108. The NewPublisherExpDialog, NewSubscriberExpDialog, and SectionOptionsExpDialog functions display the appropriate dialog box, handle user interaction, and call any functions you have provided in the dlgHook and filterProc parameters.
  3109. For the NewPublisherExpDialog and NewSubscriberExpDialog functions, all the pseudo-items for the Standard File Package such as hookFirstCall(–1), hookNullEvent(100), hookRebuildList(101), and hookLastCall(–2) can be used, as well as hookRedrawPreview(150).
  3110. For the SectionOptionsExpDialog function, the only valid pseudo-items are hookFirstCall(–1), hookNullEvent(100), hookLastCall(–2), emHookRedrawPreview(150), emHookCancelSection(160), emHookGoToPublisher(161), emHookGetEditionNow(162), emHookSendEditionNow(162), emHookManualUpdateMode(163), and emHookAutoUpdateMode(164).
  3111. If you provide an expandable dialog hook function, it must contain the following parameters:
  3112. FUNCTION MyExpDlgHook (itemOffset: Integer; itemHit: Integer;
  3113.                                 theDialog: DialogPtr; 
  3114.                                  yourDataPtr: Ptr): Integer;
  3115. If you provide an expandable modal-dialog filter function, it must contain the following parameters.
  3116. FUNCTION MyExpModalFilter (theDialog: DialogPtr; 
  3117.                                     VAR theEvent: EventRecord; 
  3118.                                     itemOffset: Integer; 
  3119.                                     VAR itemHit: Integer; 
  3120.                                     yourDataPtr: Ptr): Boolean;
  3121. SEE ALSO
  3122. See the chapter “Dialog Manager” in Inside Macintosh: Macintosh Toolbox Essentials for additional information on item lists. See the chapter “Standard File Package” in Inside Macintosh: Files for information on dialog hook and modal-dialog filter functions.
  3123.  
  3124. Locating a Publisher and Edition From a Subscriber
  3125.  
  3126. The GetEditionInfo function returns information about a section’s edition such as its location, last modification date, creator, and type.
  3127. Once you locate a section’s edition, you can use the GoToPublisherSection function to find the document containing the publisher.
  3128.  
  3129. GetEditionInfo
  3130.  
  3131. Use the GetEditionInfo function to obtain information about a section’s edition, such as its location, last modification date, creator, and type.
  3132. FUNCTION GetEditionInfo
  3133.                             (sectionH: SectionHandle; 
  3134.                              VAR editionInfo: EditionInfoRecord): OSErr;
  3135. sectionH    A handle to the section record for a given section. 
  3136. editionInfo
  3137. An edition information record. The GetEditionInfo function returns the public information contained in the section’s control block.
  3138. DESCRIPTION
  3139. The Edition Manager ensures that the existing edition name corresponds to the Finder’s existing edition name. If the controlBlock field of the section record is set to NIL or the edition cannot be located, the GetEditionInfo function returns an fnfErr result code.
  3140. The GetEditionInfo function returns information about the section’s edition in a data structure of type EditionInfoRecord.
  3141. TYPE EditionInfoRecord = 
  3142.     RECORD
  3143.         crDate:                TimeStamp;                            {date edition container }
  3144.                                                     { was created}
  3145.         mdDate:                TimeStamp;                            {date of last change}
  3146.         fdCreator:                OSType;                            {file creator}
  3147.         fdType:                OSType;                            {file type}
  3148.         container:                EditionContainerSpec;                            {the edition}
  3149.     END;
  3150. Field descriptions
  3151. crDate    The creation date of the edition. 
  3152.  
  3153. mdDate    The modification date of the edition.
  3154. fdCreator    The creator of the edition file. 
  3155. fdType    The file type of the edition file. 
  3156. container    An edition container record, which specifies the volume reference number, directory ID, filename, script, and part number for the edition.
  3157. RESULT CODESnoErr    0    No error    
  3158. fnfErr    –43    Not registered or file moved    
  3159. editionMgrInitErr    –450    Manager not initialized    
  3160.  
  3161. SEE ALSO
  3162. For an example of the use of GetEditionInfo, see Listing 2-8 beginning on page 2-46. For another use of this function, see “Canceling Sections Within Documents” beginning on page 2-48. For a description of the edition container record, see page 2-71. 
  3163.  
  3164.  
  3165. GoToPublisherSection
  3166.  
  3167. When the user wants to locate the publisher for a particular subscriber (by clicking Open Publisher in the subscriber options dialog box), the SectionOptionsDialog function returns the action code 'goto' in the action field of the section options reply record. When you receive this action code, you should open the document containing the publisher. 
  3168. First, use the GetEditionInfo function to find the edition container. Then use the GoToPublisherSection function to open the document containing the publisher.
  3169. FUNCTION GoToPublisherSection 
  3170.                                 (container: EditionContainerSpec): OSErr;
  3171. container    An edition container record, which specifies volume reference number, directory ID, and filename of the subscriber’s edition. You obtain the edition container by calling the GetEditionInfo function. 
  3172. DESCRIPTION
  3173. The GoToPublisherSection function resolves the alias in the edition to find the document containing its publisher. In general, this function internally uses the GetStandardFormats function to get the alias to the publisher document and then resolves the alias. It next sends the Finder an Apple event to open the document (which launches its application if necessary) and, after the publisher is registered, sends a Section Scroll event to the publisher.
  3174. As an optimization, if there is a registered publisher, the GoToPublisherSection function simply sends a Section Scroll event to the publisher. 
  3175. If the edition does not contain an alias and there are no registered publishers, then the GoToPublisherSection function sends an Open Documents event to open the edition to the creating application.
  3176. If the edition container is not an edition file (as is the case when you are using bottlenecks to subscribe to non-edition files), the GoToPublisherSection function sends the Finder an Apple event to open that file. 
  3177. RESULT CODESnoErr    0    No error    
  3178. fnfErr    –43    File not found    
  3179. editionMgrInitErr    –450    Manager not initialized    
  3180. badSubPartErr    –454    Invalid edition container    
  3181.  
  3182. SEE ALSO
  3183. For illustrations of the section options dialog box for subscribers, see Figure 2-15 on page 2-44 and Figure 2-16 on page 2-45. For an example of responding to the action code 'goto', see Listing 2-8 beginning on page 2-46. For a description of the edition container record, see page 2-71.
  3184.  
  3185. Edition Container Formats
  3186.  
  3187. The Edition Manager calls the GetStandardFormats function to get the alias used in the GoToPublisherSection function and to get the preview shown in the subscriber dialog box. You probably do not need to call this function directly.
  3188.  
  3189. GetStandardFormats
  3190.  
  3191. You probably do not need to call the GetStandardFormats function directly because the Edition Manager calls this function.
  3192. FUNCTION GetStandardFormats 
  3193.                     (container: EditionContainerSpec; 
  3194.                      VAR previewFormat: FormatType;
  3195.                      preview, publisherAlias, formats: Handle): OSErr;
  3196. container    An edition container record that specifies the edition volume reference number, directory ID, filename, and part.
  3197. previewFormat
  3198. The GetStandardFormats function returns in this parameter a handle to the first format of the requested format type that it finds in the edition. 
  3199. preview    A format type. The GetStandardFormats function looks for a format of the type specified in this parameter and returns in this parameter the format type of the first format that it finds. The function tries to find one of four formats: 'prvw', 'PICT', 'TEXT', or 'snd '. 
  3200. publisherAlias
  3201. The publisherAlias parameter reads the format kPublisherDocAliasFormat ('alis').
  3202. formats    The formats parameter reads the virtual format kFormatListFormat ('fmts'). 
  3203. DESCRIPTION
  3204. You should pass in valid handles for the formats that you want and NIL for the formats that you don’t want. The handles are resized to the size of the data. 
  3205. If one of the requested formats cannot be found, GetStandardFormats returns a noTypeErr result code. 
  3206. RESULT CODESnoErr    0    No error    
  3207. noTypeErr    –102    Edition container not found    
  3208. editionMgrInitErr    –450    Manager not initialized    
  3209.  
  3210.  
  3211. Reading and Writing Non-Edition Files
  3212.  
  3213. The Edition Manager never opens or closes an edition container directly—it calls the current edition opener. See “Subscribing to Non-Edition Files” beginning on page 2-62 for additional information.
  3214. To override the standard opener function, create an opener function that contains the following parameters:
  3215. FUNCTION MyOpener (selector: EditionOpenerVerb;
  3216.                          VAR PB: EditionOpenerParamBlock): OSErr;
  3217. When this function is called by the Edition Manager, the selector parameter is set to one of the edition opener verbs (eoOpen, eoClose, eoOpenNew, eoCloseNew, eoCanSubscribe). The PB parameter contains an edition opener parameter block record.
  3218. Use the GetEditionOpenerProc function to locate the current edition opener and use the SetEditionOpenerProc function to provide your own edition opener. 
  3219. Use the CallEditionOpenerProc function to call an edition opener and use the CallFormatIOProc function to call a format I/O function.
  3220.  
  3221. GetEditionOpenerProc
  3222.  
  3223. Use the GetEditionOpenerProc function to locate the current edition opener.
  3224. FUNCTION GetEditionOpenerProc
  3225.                             (VAR opener: EditionOpenerProcPtr): OSErr;
  3226. opener    The GetEditionOpenerProc function returns a pointer to the current edition opener function in this parameter.
  3227.  
  3228. SetEditionOpenerProc
  3229.  
  3230. Use the SetEditionOpenerProc function to provide your own edition opener.
  3231. FUNCTION SetEditionOpenerProc 
  3232.                             (opener: EditionOpenerProcPtr): OSErr;
  3233. opener    A pointer to the edition opener function that you are providing.
  3234.  
  3235. CallEditionOpenerProc
  3236.  
  3237. Use the CallEditionOpenerProc function to call an edition opener.
  3238. FUNCTION CallEditionOpenerProc 
  3239.                             (selector: EditionOpenerVerb; 
  3240.                              VAR PB: EditionOpenerParamBlock;
  3241.                              routine: EditionOpenerProcPtr): OSErr;
  3242. selector    An edition opener verb. When the CallEditionOpenerProc function is called by the Edition Manager, the selector parameter is set to one of the edition opener verbs (eoOpen, eoClose, eoOpenNew, eoCloseNew, eoCanSubscribe). 
  3243. PB    An edition opener parameter block. 
  3244. routine    A pointer to an edition opener function.
  3245. DESCRIPTION
  3246. The Edition Manager calls an edition opener function whenever it needs to open or close an edition. The Edition Manager passes an edition opener parameter block as one of the parameters to an edition opener function. The edition opener parameter block is defined by this structure:
  3247. TYPE EditionOpenerParamBlock = 
  3248.     RECORD
  3249.         info:                    EditionInfoRecord;                            {edition container to }
  3250.                                                         { be subscribed to}
  3251.         sectionH:                    SectionHandle;                            {publisher or }
  3252.                                                         { subscriber }
  3253.                                                         { requesting open}
  3254.         document:                    FSSpecPtr;                            {document passed}
  3255.         fdCreator:                    OSType;                            {Finder creator type}
  3256.         ioRefNum:                    LongInt;                            {reference number}
  3257.         ioProc:                    FormatIOProcPtr;                            {routine to read }
  3258.                                                         { formats}
  3259.         success:                    Boolean;                            {reading or writing }
  3260.                                                         { was successful}
  3261.         formatsMask:                    SignedByte;                            {formats required to }
  3262.                                                         { subscribe}
  3263.     END;
  3264. To override the standard reading and writing functions, you should create an I/O function that contains the following parameters.
  3265. FUNCTION MyIO (selector: FormatIOVerb; 
  3266.                     VAR PB: FormatIOParamBlock): OSErr;
  3267. Set the selector parameter to one of the format I/O verbs (ioHasFormat, ioReadFormat, ioNewFormat, ioWriteFormat). The PB parameter contains a format I/O parameter block record.
  3268. SEE ALSO
  3269. See “Calling an Edition Opener” beginning on page 2-64 for additional information.
  3270.  
  3271. CallFormatIOProc
  3272.  
  3273. Use the CallFormatIOProc function to call a format I/O function.
  3274. FUNCTION CallFormatIOProc (selector: FormatIOVerb; 
  3275.                                     VAR PB:FormatIOParamBlock; 
  3276.                                     routine: FormatIOProcPtr): OSErr;
  3277. selector    A format I/O verb (ioHasFormat, ioReadFormat, ioNewFormat, ioWriteFormat). 
  3278. PB    A format I/O parameter block record.
  3279. routine    A pointer to a format I/O function. 
  3280. DESCRIPTION
  3281. The Edition Manager calls a format I/O function whenever it needs to read from or write to an edition. The Edition Manager passes a format I/O parameter block as one of the parameters to a format I/O procedure. The format I/O parameter block is defined by this structure:
  3282. TYPE FormatIOParamBlock = 
  3283.     RECORD
  3284.         ioRefNum:                    LongInt;                    {reference number}
  3285.         format:                    FormatType;                    {edition format type}
  3286.         formatIndex:                    LongInt;                    {opener-specific enumeration } 
  3287.                                                 { of formats}
  3288.         offset:                    LongInt;                    {offset into format}
  3289.         buffPtr:                    Ptr;                    {data starts here}
  3290.         buffLen:                    LongInt;                    {length of data}
  3291.     END;
  3292. SEE ALSO
  3293. See “Calling a Format I/O Function” beginning on page 2-68 for additional information.
  3294.  
  3295. Application-Defined Routines
  3296.  
  3297. Your application can provide an edition opener function, format I/O function, expandable dialog hook function, and expandable modal-dialog filter function. For the routine declarations of the edition opener and format I/O functions, see “Reading and Writing Non-Edition Files” beginning on page 2-102. For the routine declarations of the expandable dialog hook and expandable modal-dialog filter functions, see the description of NewSubscriberExpDialog, NewPublisherExpDialog, and SectionOptionsExpDialog beginning on page 2-96. 
  3298.  
  3299.  
  3300. Summary of the Edition Manager
  3301.  
  3302.  
  3303. Pascal Summary
  3304.  
  3305.  
  3306. Constants
  3307.  
  3308. CONST        
  3309.     {resource types}
  3310.     rSectionType                                        = 'sect';                {resource type for a }
  3311.                                                             { section}
  3312.     {section types}
  3313.     stSubscriber                                        = $01;                {subscriber section type}
  3314.     stPublisher                                        = $0A;                {publisher section type} 
  3315.     {update modes}
  3316.     sumAutomatic                                        = 0;                {subscriber receives new } 
  3317.                                                             { editions automatically}
  3318.     sumManual                                        = 1;                {subscriber receives new } 
  3319.                                                             { editions manually}
  3320.     pumOnSave                                        = 0;                {publisher sends new } 
  3321.                                                             { editions on save}
  3322.     pumManual                                        = 1;                {publisher does not send } 
  3323.                                                             { new editions until user }
  3324.                                                             { request}
  3325.     {edition container subpart number}
  3326.     kPartsNotUsed                                        = 0;                {edition is the whole file}
  3327.     kPartNumberUnknown                                        = -1;                {not used in version 7.0} 
  3328.  
  3329.     {preview size}
  3330.     kPreviewWidth                                        = 120;                {preview width} 
  3331.     kPreviewHeight                                        = 120;                {preview height}
  3332.  
  3333.     {special formats}
  3334.     kPublisherDocAliasFormat                                        = 'alis';                {alias record from the } 
  3335.                                                             { edition to publisher} 
  3336.     kPreviewFormat                                        = 'prvw';                {'PICT' thumbnail sketch}
  3337.     kFormatListFormat                                        = 'fmts';                {list of all available }
  3338.                                                             { formats and their sizes}
  3339.  
  3340.     {bits for formatMask}
  3341.     kPICTformatMask                                        = 1;                {graphics format}
  3342.     kTEXTformatMask                                        = 2;                {text format}
  3343.     ksndFormatMask                                        = 4;                {sound format}
  3344.  
  3345.     {Finder types for edition files}
  3346.     kPICTEditionFileType                                        = 'edtp';                {contains 'PICT', }
  3347.     kTEXTEditionFileType                                        = 'edtt';                { 'TEXT', and }
  3348.     ksndEditionFileType                                        = 'edts';                { 'snd ' file types}
  3349.     kUnknownEditionFileType                                        = 'edtu';                {unknown file type}
  3350.     {miscellaneous}
  3351.     kFormatLengthUnknown                                        = -1;                    {length of format unknown}
  3352.  
  3353.     {message IDs for Apple events sent by the Edition Manager}
  3354.     sectionEventMsgClass                                        = 'sect';                {Apple events sent by the }
  3355.                                                             { Edition Manager}
  3356.     sectionReadMsgID                                        = 'read';                {Section Read events}
  3357.     sectionWriteMsgID                                        = 'writ';                {Section Write events}
  3358.     sectionScrollMsgID                                        = 'scrl';                {Section Scroll events}
  3359.     sectionCancelMsgID                                        = 'cncl';                {Section Cancel events}
  3360.  
  3361.     {refCon field when displaying stacked dialog boxes}
  3362.     sfMainDialogRefCon                                        = 'stdf';                {new publisher and }
  3363.                                                             { new subscriber}
  3364.     sfNewFolderDialogRefCon                                        = 'nfdr';                {new folder}
  3365.     sfReplaceDialogRefCon                                        = 'rplc';                {replace dialog}
  3366.     sfStatWarnDialogRefCon                                        = 'stat';                {warning dialog}
  3367.     sfErrorDialogRefCon                                        = 'err ';                {error dialog}
  3368.     emOptionsDialogRefCon                                        = 'optn';                {options dialog}
  3369.     emCancelSectionDialogRefCon                                        = 'cncl';                {cancel section}
  3370.     emGotoPubErrDialogRefCon                                        = 'gerr';                {locate publisher}
  3371.  
  3372.     {pseudo-item hits for dialogHooks}
  3373.     emHookRedrawPreview                                        = 150;                {for NewPublisher or }
  3374.                                                             { NewSubscriber dialogs}
  3375.     emHookCancelSection                                        = 160;                {for SectionOptions dialog}
  3376.     emHookGoToPublisher                                        = 161;                {for SectionOptions dialog}
  3377.     emHookGetEditionNow                                        = 162;                {for SectionOptions dialog}
  3378.     emHookSendEditionNow                                        = 162;                {for SectionOptions dialog}
  3379.     emHookManualUpdateMode                                        = 163;                {for SectionOptions dialog}
  3380.     emHookAutoUpdateMode                                        = 164;                {for SectionOptions dialog}
  3381.  
  3382.  
  3383. Data Types
  3384.  
  3385. TYPE TimeStamp                                            = LongInt;                    {seconds since 1904}
  3386.     EditionRefNum                                         = Handle;                     {for use in Edition I/O}
  3387.     UpdateMode                                         = Integer;                    {sumAutomatic, }
  3388.                                                                 { sumManual, } 
  3389.                                                                 { pumOnSave, pumManual}
  3390.     SectionType                                         = SignedByte;                    {stSubscriber or }
  3391.                                                                 { stPublisher} 
  3392.     FormatType                                         = PACKED ARRAY[1..4] OF CHAR; 
  3393.                                                                 {similar to ResType used } 
  3394.                                                                 { by the Scrap Manager}
  3395.  
  3396.     SectionHandle                                        = ^SectionPtr;
  3397.     SectionPtr                                        = ^SectionRecord;
  3398.     SectionRecord                                         = 
  3399.     RECORD
  3400.         version:                                    SignedByte;                    {always 1 in version 7.0}
  3401.         kind:                                    SectionType;                    {publisher or subscriber}
  3402.         mode:                                    UpdateMode;                    {automatic or manual}
  3403.         mdDate:                                    TimeStamp;                    {last change to section}
  3404.         sectionID:                                    LongInt;                    {application-specific, }
  3405.                                                                 { unique per document}
  3406.         refCon:                                    LongInt;                    {application-specific}
  3407.         alias:                                    AliasHandle;                    {handle to alias record}
  3408.  
  3409.         {The following fields are private and are set up by the }
  3410.         { RegisterSection function.}
  3411.  
  3412.         subPart:                                    LongInt;                    {private}
  3413.         nextSection:                                    SectionHandle;                    {private}
  3414.         controlBlock:                                    Handle;                    {private}
  3415.         refNum:                                    EditionRefNum;                    {private}
  3416.     END;
  3417.     EditionContainerSpecPtr =^EditionContainerSpec;
  3418.     EditionContainerSpec =
  3419.     RECORD
  3420.         theFile:                                    FSSpec;                    {file containing edition } 
  3421.                                                                 { data}
  3422.         theFileScript:                                     ScriptCode;                    {script code of filename}
  3423.         thePart:                                    LongInt;                    {which part of file, } 
  3424.                                                                 { always kPartsNotUsed}
  3425.         thePartName:                                    Str31;                    {reserved}
  3426.         thePartScript:                                     ScriptCode;                    {reserved}
  3427.     END;
  3428.     FormatsAvailable = ARRAY[0..0] OF
  3429.     RECORD
  3430.         theType:                                    FormatType;                    {format type for an }
  3431.                                                                 { edition}
  3432.         theLength:                                    LongInt;                    {length of edition format }
  3433.                                                                 { type}
  3434.     END;
  3435.     EditionInfoRecord = 
  3436.     RECORD
  3437.         crDate:                                    TimeStamp;                    {date edition container }
  3438.                                                                 { was created}
  3439.         mdDate:                                    TimeStamp;                    {date of last change}
  3440.         fdCreator:                                    OSType;                    {file creator}
  3441.         fdType:                                    OSType;                    {file type}
  3442.         container:                                    EditionContainerSpec;
  3443.                                                                 {the edition}
  3444.     END;
  3445.     NewPublisherReply = 
  3446.     RECORD
  3447.         canceled:                        Boolean;                            {user canceled dialog box} 
  3448.         replacing:                        Boolean;                            {user chose existing } 
  3449.                                                             { filename for an edition}
  3450.         usePart:                        Boolean;                            {always FALSE in version 7.0}
  3451.         preview:                        Handle;                            {handle to 'prvw', 'PICT',}
  3452.                                                             { 'TEXT', or 'snd ' data}
  3453.         previewFormat:                        FormatType;                            {type of preview}
  3454.         container:                        EditionContainerSpec;
  3455.                                                             {edition chosen}
  3456.     END;
  3457.     NewSubscriberReply =
  3458.     RECORD
  3459.         canceled:                        Boolean;                            {user canceled dialog box}
  3460.         formatsMask:                        SignedByte;                            {formats required}
  3461.         container:                         EditionContainerSpec;
  3462.                                                             {edition selected}
  3463.     END;
  3464.     SectionOptionsReply =
  3465.     RECORD
  3466.         canceled:                        Boolean;                            {user canceled dialog box}
  3467.         changed:                         Boolean;                            {changed the section }
  3468.                                                             { record}
  3469.         sectionH:                        SectionHandle;                            {handle to the specified }
  3470.                                                             { section record}
  3471.         action:                        ResType;                            {action codes}
  3472.     END;
  3473.     EditionOpenerVerb    = (eoOpen, eoClose, eoOpenNew, eoCloseNew,
  3474.                                 eoCanSubscribe); 
  3475.     EditionOpenerParamBlock = 
  3476.     RECORD
  3477.         info:                        EditionInfoRecord;                            {edition container to }
  3478.                                                             { be subscribed to}
  3479.         sectionH:                        SectionHandle;                            {publisher or subscriber }
  3480.                                                             { requesting open}
  3481.         document:                        FSSpecPtr;                            {document passed}
  3482.         fdCreator:                        OSType;                            {Finder creator type}
  3483.         ioRefNum:                        LongInt;                            {reference number}
  3484.         ioProc:                        FormatIOProcPtr;                            {routine to read formats}
  3485.         success:                        Boolean;                            {reading or writing was }
  3486.                                                             { successful}
  3487.         formatsMask:                        SignedByte;                            {formats required to }
  3488.                                                             { subscribe}
  3489.     END;
  3490.     FormatIOVerb     = (ioHasFormat, ioReadFormat, ioNewFormat, ioWriteFormat);
  3491.     FormatIOParamBlock = 
  3492.     RECORD
  3493.         ioRefNum:                        LongInt;                            {reference number}
  3494.         format:                        FormatType;                            {edition format type}
  3495.         formatIndex:                        LongInt;                            {opener-specific enumeration }
  3496.                                                             { of formats}
  3497.         offset:                        LongInt;                            {offset into format}
  3498.         buffPtr:                        Ptr;                            {data starts here}
  3499.         buffLen:                        LongInt;                            {length of data}
  3500. END;
  3501.  
  3502.  
  3503. Edition Manager Routines
  3504.  
  3505. Initializing the Edition Manager
  3506. FUNCTION InitEditionPack     : OSErr;
  3507. Creating and Registering a Section
  3508. FUNCTION NewSection    (container: EditionContainerSpec; sectionDocument: FSSpecPtr; kind: SectionType; sectionID: LongInt; initialMode: UpdateMode; VAR sectionH: SectionHandle): OSErr;
  3509. FUNCTION RegisterSection    (sectionDocument: FSSpec; 
  3510. sectionH: SectionHandle; 
  3511. VAR aliasWasUpdated: Boolean)
  3512. : OSErr;
  3513. FUNCTION UnRegisterSection    (sectionH: SectionHandle): OSErr;
  3514. FUNCTION IsRegisteredSection
  3515. (sectionH: SectionHandle): OSErr;
  3516. FUNCTION AssociateSection    (sectionH: SectionHandle; 
  3517. newSectionDocument: FSSpecPtr): OSErr;
  3518. Creating and Deleting an Edition Container
  3519. FUNCTION CreateEditionContainerFile
  3520. (editionFile: FSSpec; fdCreator: OSType; editionFileNameScript: ScriptCode): OSErr;
  3521. FUNCTION DeleteEditionContainerFile
  3522. (editionFile: FSSpec): OSErr;
  3523. Setting and Getting a Format Mark
  3524. FUNCTION SetEditionFormatMark
  3525. (whichEdition: EditionRefNum; 
  3526. whichFormat: FormatType; 
  3527. setMarkTo: LongInt): OSErr;
  3528. FUNCTION GetEditionFormatMark
  3529. (whichEdition: EditionRefNum; 
  3530. whichFormat: FormatType; 
  3531. VAR currentMark: LongInt): OSErr; 
  3532. Reading in Edition Data
  3533. FUNCTION OpenEdition    (subscriberSectionH: SectionHandle; 
  3534. VAR refNum: EditionRefNum): OSErr;
  3535. FUNCTION EditionHasFormat    (whichEdition: EditionRefNum; 
  3536. whichFormat: FormatType; 
  3537. VAR formatSize: Size): OSErr; 
  3538. FUNCTION ReadEdition    (whichEdition: EditionRefNum; 
  3539. whichFormat: FormatType; buffPtr: UNIV Ptr; VAR buffLen: Size): OSErr;
  3540. Writing out Edition Data
  3541. FUNCTION OpenNewEdition    (publisherSectionH: SectionHandle; 
  3542. fdCreator: OSType; 
  3543. publisherSectionDocument: FSSpecPtr; 
  3544. VAR refNum: EditionRefNum): OSErr;
  3545. FUNCTION WriteEdition    (whichEdition: EditionRefNum; 
  3546. whichFormat: FormatType; buffPtr: UNIV Ptr; buffLen: Size): OSErr;
  3547. Closing an Edition After Reading or Writing
  3548. FUNCTION CloseEdition    (whichEdition: EditionRefNum; 
  3549. successful: Boolean): OSErr;
  3550. Displaying Dialog Boxes
  3551. FUNCTION GetLastEditionContainerUsed
  3552. (VAR container: EditionContainerSpec): OSErr;
  3553. FUNCTION NewSubscriberDialog
  3554. (VAR reply: NewSubscriberReply): OSErr;
  3555. FUNCTION NewPublisherDialog    (VAR reply: NewPublisherReply): OSErr;
  3556. FUNCTION SectionOptionsDialog
  3557. (VAR reply: SectionOptionsReply): OSErr;
  3558. FUNCTION NewSubscriberExpDialog
  3559. (VAR reply: NewSubscriberReply; where: Point; expansionDITLresID: Integer; 
  3560. dlgHook: ExpDlgHookProcPtr; 
  3561. filterProc: ExpModalFilterProcPtr; yourDataPtr: UNIV Ptr): OSErr;
  3562. FUNCTION NewPublisherExpDialog
  3563. (VAR reply: NewPublisherReply; where: Point; expansionDITLresID: Integer; 
  3564. dlgHook: ExpDlgHookProcPtr; 
  3565. filterProc: ExpModalFilterProcPtr; yourDataPtr: UNIV Ptr): OSErr;
  3566. FUNCTION SectionOptionsExpDialog
  3567. (VAR reply: SectionOptionsReply; where: Point; expansionDITLresID: Integer; 
  3568. dlgHook: ExpDlgHookProcPtr; 
  3569. filterProc: ExpModalFilterProcPtr; yourDataPtr: UNIV Ptr): OSErr;
  3570. Locating a Publisher and Edition From a Subscriber
  3571. FUNCTION GetEditionInfo    (sectionH: SectionHandle; 
  3572. VAR editionInfo: EditionInfoRecord): OSErr;
  3573. FUNCTION GoToPublisherSection
  3574. (container: EditionContainerSpec): OSErr;
  3575. Edition Container Formats
  3576. FUNCTION GetStandardFormats    (container: EditionContainerSpec; 
  3577. VAR previewFormat: FormatType; 
  3578. preview, publisherAlias, 
  3579. formats: Handle): OSErr;
  3580. Reading and Writing Non-Edition files
  3581. FUNCTION GetEditionOpenerProc
  3582. (VAR opener: EditionOpenerProcPtr): OSErr;
  3583. FUNCTION SetEditionOpenerProc
  3584. (opener: EditionOpenerProcPtr): OSErr;
  3585. FUNCTION CallEditionOpenerProc
  3586. (selector: EditionOpenerVerb; 
  3587. VAR PB: EditionOpenerParamBlock; 
  3588. routine: EditionOpenerProcPtr): OSErr;
  3589. FUNCTION CallFormatIOProc    (selector: FormatIOVerb; 
  3590. VAR PB: FormatIOParamBlock; 
  3591. routine: FormatIOProcPtr): OSErr;
  3592.  
  3593. Application-Defined Routines
  3594.  
  3595. FUNCTION MyExpDlgHook    (itemOffset: Integer; itemHit: Integer; 
  3596. theDialog: DialogPtr; 
  3597. yourDataPtr: Ptr): Integer;
  3598. FUNCTION MyExpModalFilter    (theDialog: DialogPtr; 
  3599. VAR theEvent: EventRecord; 
  3600. itemOffset: Integer; VAR itemHit: Integer; yourDataPtr: Ptr): Boolean;
  3601. FUNCTION MyOpener    (selector: EditionOpenerVerb; 
  3602. VAR PB: EditionOpenerParamBlock): OSErr;
  3603. FUNCTION MyIO    (selector: FormatIOVerb; 
  3604. VAR PB: FormatIOParamBlock): OSErr;
  3605.  
  3606. C Summary
  3607.  
  3608.  
  3609. Constants
  3610.  
  3611. CONST        
  3612. enum {
  3613.     /*resource types*/
  3614.     #define rSectionType                                         'sect'                /*resource type for a */
  3615.                                                             /* section*/
  3616.  
  3617.     /*section types*/
  3618.     stSubscriber                                        = 0x01,                /*subscriber section type*/
  3619.     stPublisher                                        = 0x0A,                /*publisher section type*/ 
  3620.  
  3621.     /*update modes*/
  3622.     sumAutomatic                                        = 0,                /*subscriber receives new */ 
  3623.                                                             /* editions automatically*/
  3624.     sumManual                                        = 1,                /*subscriber receives new */ 
  3625.                                                             /* editions manually*/
  3626.     pumOnSave                                        = 0,                /*publisher sends new */ 
  3627.                                                             /* editions on save*/
  3628.     pumManual                                        = 1,                /*publisher does not send */ 
  3629.                                                             /* new editions until user */
  3630.                                                             /* request*/
  3631.     /*edition container subpart number*/
  3632.     kPartsNotUsed                                        = 0,                /*edition is the whole file*/
  3633.     kPartNumberUnknown                                        = -1,                /*not used in version 7.0*/ 
  3634.  
  3635.     /*preview size*/
  3636.     kPreviewWidth                                        = 120,                /*preview width*/ 
  3637.     kPreviewHeight                                        = 120,                /*preview height*/
  3638.     /*special formats*/
  3639.     #define kPublisherDocAliasFormat                                         'alis'                /*alias record from the */ 
  3640.                                                             /* edition to publisher*/ 
  3641.     #define kPreviewFormat                                            'prvw'            /*'PICT' thumbnail sketch*/
  3642.     #define kFormatListFormat                                             'fmts'            /*list of all available */
  3643.                                                             /* formats and their sizes*/
  3644.  
  3645.     /*bits for formatMask*/
  3646.     kPICTformatMask                                        = 1,                /*graphics format*/
  3647.     kTEXTformatMask                                        = 2,                /*text format*/
  3648.     ksndFormatMask                                        = 4,                /*sound format*/
  3649.  
  3650.     /*Finder types for edition files*/
  3651.     #define kPICTEditionFileType                                             'edtp'            /*contains 'PICT', */
  3652.     #define kTEXTEditionFileType                                             'edtt'            /* 'TEXT', and */
  3653.     #define ksndEditionFileType                                             'edts'            /* 'snd ' file types*/
  3654.     #define kUnknownEditionFileType                                             'edtu'            /*unknown file type*/
  3655.  
  3656.     /*pseudo-item hits for dialogHooks*/
  3657.     emHookRedrawPreview                                        = 150,                /*for NewPublisher or */
  3658.                                                             /* NewSubscriber dialogs*/
  3659.     emHookCancelSection                                        = 160,                /*for SectionOptions dialog*/
  3660.     emHookGoToPublisher                                        = 161,                /*for SectionOptions dialog*/
  3661.     emHookGetEditionNow                                        = 162,                /*for SectionOptions dialog*/
  3662.     emHookSendEditionNow                                        = 162,                /*for SectionOptions dialog*/
  3663.     emHookManualUpdateMode                                        = 163,                /*for SectionOptions dialog*/
  3664.     emHookAutoUpdateMode                                        = 164                /*for SectionOptions dialog*/
  3665. };
  3666.     /*edition opener verbs*/
  3667. enum {eoOpen, eoClose, eoOpenNew, eoCloseNew, eoCanSubscribe};
  3668.  
  3669. enum {
  3670.     /*refCon field when displaying stacked dialog boxes*/
  3671.     #define emOptionsDialogRefCon                                                 'optn'                /*options dialog*/
  3672.     #define emCancelSectionDialogRefCon                                                 'cncl'                /*cancel section*/
  3673.     #define emGotoPubErrDialogRefCon                                                 'gerr'                /*locate publisher*/
  3674.  
  3675.     kFormatLengthUnknown                                        = -1                 /*length of format unknown*/
  3676. };
  3677.     /*refCon field when displaying stacked dialog boxes*/
  3678.     #define sfMainDialogRefCon                                         'stdf'                {new publisher and }
  3679.                                                             { new subscriber}
  3680.     #define sfNewFolderDialogRefCon                                        'nfdr'                {new folder}
  3681.     #define sfReplaceDialogRefCon                                         'rplc'                {replace dialog}
  3682.     #define sfStatWarnDialogRefCon     'stat'                                                    {warning dialog}
  3683.     #define sfErrorDialogRefCon                                         'err '                {error dialog}
  3684.  
  3685.     /*message IDs for Apple events sent by the Edition Manager*/
  3686.     #define sectionEventMsgClass                                         'sect'                /*Apple events sent by the */
  3687.                                                             /* Edition Manager*/
  3688.     #define sectionReadMsgID                                         'read'                /*Section Read events*/
  3689.     #define sectionWriteMsgID                                         'writ'                /*Section Write events*/
  3690.     #define sectionScrollMsgID                                         'scrl'                /*Section Scroll events*/
  3691.     #define sectionCancelMsgID                                         'cncl'                /*Section Cancel events*/
  3692.  
  3693. Data Types
  3694.  
  3695. typedef unsigned long TimeStamp;                                                            /*seconds since 1904*/
  3696. typedef Handle EditionRefNum;                            ‘                                /*used in Edition I/O*/
  3697. typedef short UpdateMode;                                                            /*update mode: sumAutomatic, */
  3698.                                                             /* sumManual, */ 
  3699.                                                             /* pumOnSave, pumManual*/
  3700. typedef char SectionType;                                                            /*one byte, stSubscriber */
  3701.                                                             /* or stPublisher*/ 
  3702. typedef unsigned long FormatType;                                                            /*similar to ResType*/
  3703.  
  3704. struct SectionRecord {
  3705.     SignedByte version;                                                        /*always 1x01 in version 7.0*/
  3706.     SectionType kind;                                                        /*stPublisher or */
  3707.                                                             /* stSubscriber*/
  3708.     UpdateMode mode;                                                        /*automatic or manual*/
  3709.     TimeStamp mdDate;                                                        /*last change to section*/
  3710.     long sectionID;                                                        /*application-specific, */
  3711.                                                             /* unique per document*/
  3712.     long refCon;                                                        /*application-specific*/
  3713.     AliasHandle alias;                                                        /*handle to alias record*/
  3714.     long subPart;                                                        /*private*/
  3715.     struct SectionRecord **nextSection;                                                        /*private*/
  3716.     Handle controlBlock;                                                        /*private*/
  3717.     EditionRefNum refNum;                                                        /*private*/
  3718. };
  3719.  
  3720. typedef struct SectionRecord SectionRecord;
  3721. typedef SectionRecord *SectionPtr, **SectionHandle;
  3722.  
  3723.  
  3724. struct EditionContainerSpec {
  3725.     FSSpec theFile;                                                        /*file containing */ 
  3726.                                                             /* edition data*/
  3727.     ScriptCode theFileScript;                                                         /*script code of filename*/
  3728.     long thePart;                                                        /*which part of file, */ 
  3729.                                                             /* always kPartsNotUsed*/
  3730.     Str31 thePartName;                                                        /*reserved*/
  3731.     ScriptCode thePartScript;                                                         /*reserved*/
  3732. };
  3733.  
  3734. typedef struct EditionContainerSpec EditionContainerSpec;
  3735. typedef EditionContainerSpec *EditionContainerSpecPtr;
  3736.  
  3737. struct EditionInfoRecord {
  3738.     TimeStamp crDate;                                                    /*date edition container */
  3739.                                                         /* was created*/
  3740.     TimeStamp mdDate;                                                    /*date of last change*/
  3741.     OSType fdCreator;                                                    /*file creator*/
  3742.     OSType fdType;                                                    /*file type*/
  3743.     EditionContainerSpec container;                                                    /*the edition*/
  3744. };
  3745.  
  3746. typedef struct EditionInfoRecord EditionInfoRecord;
  3747.  
  3748. struct NewPublisherReply {
  3749.     Boolean canceled;                                                    /*user canceled dialog box*/ 
  3750.     Boolean replacing;                                                    /*user chose existing */ 
  3751.                                                         /* filename for an edition*/
  3752.     Boolean usePart;                                                    /*always FALSE in version */ 
  3753.                                                         /* 7.0*/
  3754.     Handle preview;                                                    /*handle to 'prvw', 'PICT',*/
  3755.                                                         /* 'TEXT', or 'snd ' data*/
  3756.     FormatType previewFormat;                                                    /*type of preview*/
  3757.     EditionContainerSpec container;                                                    /*edition chosen*/
  3758. };
  3759. typedef struct NewPublisherReply NewPublisherReply;
  3760.  
  3761. struct NewSubscriberReply {
  3762.     Boolean canceled;                                                    /*user canceled dialog box*/
  3763.     unsigned char formatsMask;                                                    /*formats required*/
  3764.     EditionContainerSpec container;                                                     /*edition selected*/
  3765. };
  3766. typedef struct NewSubscriberReply NewSubscriberReply;
  3767. struct SectionOptionsReply {
  3768.     Boolean canceled;                                                    /*user canceled dialog box*/
  3769.     Boolean changed;                                                     /*changed the section */
  3770.                                                         /* record*/
  3771.     SectionHandle sectionH;                                                    /*handle to the specified */
  3772.                                                         /* section record*/
  3773.     ResType action;                                                    /*action codes*/
  3774. };
  3775.  
  3776. typedef struct SectionOptionsReply SectionOptionsReply;
  3777.  
  3778. typedef pascal Boolean (*ExpModalFilterProcPtr) (DialogPtr theDialog, 
  3779.                                                 EventRecord *theEvent, short itemOffset, 
  3780.                                                 short *itemHit, Ptr yourDataPtr);
  3781.  
  3782. typedef pascal short (*ExpDlgHookProcPtr) (short itemOffset, short itemHit,
  3783.                                                      DialogPtr theDialog, Ptr yourDataPtr);
  3784.  
  3785. typedef unsigned char EditionOpenerVerb;
  3786.     
  3787. struct EditionOpenerParamBlock {
  3788.     EditionInfoRecord info;                                                    /*edition container to */
  3789.                                                         /* be subscribed to*/
  3790.     SectionHandle sectionH;                                                    /*publisher or subscriber */
  3791.                                                         /* requesting open*/
  3792.     FSSpecPtr document;                                                    /*document passed*/
  3793.     OSType fdCreator;                                                    /*Finder creator type*/
  3794.     long ioRefNum;                                                    /*reference number*/
  3795.     FormatIOProcPtr ioProc;                                                    /*routine to read formats*/
  3796.     Boolean success;                                                    /*reading or writing was */
  3797.                                                         /* successful*/
  3798.     unsigned char formatsMask;                                                    /*formats required to */
  3799.                                                         /* subscribe*/
  3800. };
  3801. typedef struct EditionOpenerParamBlock EditionOpenerParamBlock;
  3802.  
  3803. typedef pascal short (*EditionOpenerProcPtr) (EditionOpenerVerb selector,
  3804.                                                             FormatIOParamBlock *PB);
  3805.  
  3806. enum {ioHasFormat, ioReadFormat, ioNewFormat, ioWriteFormat};
  3807. typedef unsigned char FormatIOVerb;
  3808.  
  3809.  
  3810. struct FormatIOParamBlock {
  3811.     long ioRefNum;                                                    /*reference number*/
  3812.     FormatType format;                                                    /*edition format type*/
  3813.     long formatIndex;                                                    /* opener-specific */ 
  3814.                                                         /* enumeration */
  3815.                                                         /* of formats*/
  3816.     unsigned long offset;                                                    /*offset into format*/
  3817.     Ptr buffPtr;                                                    /*data starts here*/
  3818.     unsigned long buffLen;                                                    /*length of data*/
  3819. };
  3820.  
  3821. typedef struct FormatIOParamBlock FormatIOParamBlock;
  3822.  
  3823. typedef pascal short (*FormatIOProcPtr) (FormatIOVerb selector,
  3824.                                                     FormatIOParamBlock *PB);
  3825.  
  3826. Edition Manager Routines
  3827.  
  3828. Initializing the Edition Manager
  3829. pascal OSErr InitEditionPack    (void)
  3830. Creating and Registering a Section
  3831. pascal OSErr NewSection    (const EditionContainerSpec *container,
  3832. const FSSpec *sectionDocument,
  3833. SectionType kind, long sectionID,
  3834. UpdateMode initialMode,
  3835. SectionHandle *sectionH);
  3836. pascal OSErr RegisterSection
  3837. (const FSSpec *sectionDocument,
  3838. SectionHandle sectionH,
  3839. Boolean *aliasWasUpdated);
  3840. pascal OSErr UnRegisterSection
  3841. (SectionHandle sectionH);
  3842. pascal OSErr IsRegisteredSection
  3843. (SectionHandle sectionH);
  3844. pascal OSErr AssociateSection
  3845. (SectionHandle sectionH,
  3846. const FSSpec *newSectionDocument);
  3847. Creating and Deleting an Edition Container
  3848. pascal OSErr CreateEditionContainerFile
  3849. (const FSSpec *editionFile, OSType fdCreator, ScriptCode editionFileNameScript);
  3850. pascal OSErr DeleteEditionContainerFile
  3851. (const FSSpec *editionFile);
  3852. Setting and Getting a Format Mark
  3853. pascal OSErr SetEditionFormatMark
  3854. (EditionRefNum whichEdition,
  3855. FormatType whichFormat,
  3856. unsigned long setMarkTo);
  3857. pascal OSErr GetEditionFormatMark
  3858. (EditionRefNum whichEdition,
  3859. FormatType whichFormat,
  3860. unsigned long *currentMark);
  3861. Reading in Edition Data
  3862. pascal OSErr OpenEdition    (SectionHandle subscriberSectionH, EditionRefNum *refNum);
  3863. pascal OSErr EditionHasFormat
  3864. (EditionRefNum whichEdition,
  3865. FormatType whichFormat,
  3866. Size *formatSize);
  3867. pascal OSErr ReadEdition    (EditionRefNum whichEdition,
  3868. FormatType whichFormat, void *buffPtr,
  3869. Size *buffLen);
  3870. Writing out Edition Data
  3871. pascal OSErr OpenNewEdition    (SectionHandle publisherSectionH,
  3872. OSType fdCreator,
  3873. const FSSpec *publisherSectionDocument,
  3874. EditionRefNum *refNum);
  3875. pascal OSErr WriteEdition    (EditionRefNum whichEdition,
  3876. FormatType whichFormat, const void *buffPtr, Size *buffLen);
  3877. Closing an Edition After Reading or Writing
  3878. pascal OSErr CloseEdition    (EditionRefNum whichEdition,
  3879. Boolean successful);
  3880. Displaying Dialog Boxes
  3881. pascal OSErr GetLastEditionContainerUsed
  3882. (EditionContainerSpec *container);
  3883. pascal OSErr NewSubscriberDialog
  3884. (NewSubscriberReply *reply);
  3885. pascal OSErr NewPublisherDialog
  3886. (NewPublisherReply *reply);
  3887. pascal OSErr SectionOptionsDialog
  3888. (SectionOptionsReply *reply);
  3889. pascal OSErr NewSubscriberExpDialog
  3890. (NewSubscriberReply *reply, Point where,
  3891. short expansionDITLresID,
  3892. ExpDlgHookProcPtr dlgHook,
  3893. ExpModalFilterProcPtr filterProc,
  3894. void *yourDataPtr);
  3895. pascal OSErr NewPublisherExpDialog
  3896. (NewPublisherReply *reply, Point where,
  3897. short expansionDITLresID,
  3898. ExpDlgHookProcPtr dlgHook,
  3899. ExpModalFilterProcPtr filterProc,
  3900. void *yourDataPtr);
  3901. pascal OSErr SectionOptionsExpDialog
  3902. (SectionOptionsReply *reply, Point where, 
  3903. short expansionDITLresID,
  3904. ExpDlgHookProcPtr dlgHook,
  3905. ExpModalFilterProcPtr filterProc,
  3906. void *yourDataPtr);
  3907. Locating a Publisher and Edition From a Subscriber
  3908. pascal OSErr GetEditionInfo    (const SectionHandle sectionH,
  3909. EditionInfoRecord *editionInfo);
  3910. pascal OSErr GoToPublisherSection
  3911. (const EditionContainerSpec *container);
  3912. Edition Container Formats
  3913. pascal OSErr GetStandardFormats
  3914. (const EditionContainerSpec *container,
  3915. FormatType *previewFormat,
  3916. Handle preview, Handle publisherAlias,
  3917. Handle formats);
  3918. Reading and Writing Non-Edition files
  3919. pascal OSErr GetEditionOpenerProc
  3920. (EditionOpenerProcPtr *opener);
  3921. pascal OSErr SetEditionOpenerProc
  3922. (EditionOpenerProcPtr opener);
  3923. pascal OSErr CallEditionOpenerProc
  3924. (EditionOpenerVerb selector,
  3925. EditionOpenerParamBlock *PB,
  3926. EditionOpenerProcPtr routine);
  3927. pascal OSErr CallFormatIOProc
  3928. (FormatIOVerb selector,
  3929. FormatIOParamBlock *PB,
  3930. FormatIOProcPtr routine);
  3931.  
  3932. Application-Defined Routines
  3933.  
  3934. pascal OSErr MyExpDlgHook    (short itemOffset, short itemHit,
  3935. DialogPtr theDialog,
  3936. Ptr yourDataPtr);
  3937. pascal OSErr MyExpModalFilter
  3938. (DialogPtr theDialog,
  3939. EventRecord *theEvent,
  3940. short itemOffset, short *itemHit, 
  3941. Ptr yourDataPtr);
  3942. pascal OSErr MyOpener    (EditionOpenerVerb selector,
  3943. EditionOpenerParamBlock *PB);
  3944. pascal OSErr MyIO    (FormatIOVerb selector,
  3945. FormatIOParamBlock *PB);
  3946.  
  3947. Result CodesnoErr    0    No error    
  3948. abortErr    –27    Publisher has written a new edition    
  3949. dskFulErr    –34    Disk is full    
  3950. nsvErr    –35    No such volume    
  3951. ioErr    –36    I/O error    
  3952. bdNamErr    –37    Bad filename    
  3953. fnOpnErr    –38    File not open    
  3954. eofErr    –39    No additional data in the format    
  3955. fnfErr    –43    Edition container not found    
  3956. flLckedErr    –45    Publisher writing to an edition    
  3957. fBsyErr    –47    Section doing I/O    
  3958. paramErr    –50    Invalid parameter    
  3959. rfNumErr    –51    Bad edition reference number    
  3960. permErr    –54    Not a subscriber    
  3961. wrPermErr    –61    Not a publisher    
  3962. noTypeErr    –102    Format not available    
  3963. memFullErr    –108    Memory full    
  3964. dirNFErr    –120    Directory not found    
  3965. userCanceledErr    –128    User clicked Cancel in dialog box    
  3966. editionMgrInitErr    –450    Manager not initialized or could not load package    
  3967. badSectionErr    –451    Not a valid section type    
  3968. notRegisteredSectionErr    –452    Not registered    
  3969. badSubPartErr    –454    Bad edition container spec or invalid edition container    
  3970. multiplePublisherWrn    –460    Already is a publisher    
  3971. containerNotFoundWrn    –461    Alias was not resolved    
  3972. notThePublisherWrn    –463    Not the publisher    
  3973.  
  3974.  
  3975.  
  3976. Listing 3-0
  3977. Table 3-0
  3978. Introduction to Apple Events
  3979. Contents
  3980. About Apple Events3-3
  3981. Apple Events and Apple Event Objects3-6
  3982. Apple Event Attributes and Parameters3-7
  3983. Apple Event Attributes3-8
  3984. Apple Event Parameters3-9
  3985. Interpreting Apple Event Attributes and Parameters3-10
  3986. Data Structures Within Apple Events3-12
  3987. Descriptor Records3-12
  3988. Keyword-Specified Descriptor Records3-15
  3989. Descriptor Lists3-16
  3990. Responding to Apple Events3-20
  3991. Accepting and Processing Apple Events3-20
  3992. About Apple Event Handlers3-23
  3993. Extracting and Checking Data3-23
  3994. Interacting With the User3-25
  3995. Performing the Requested Action and Returning a Result3-25
  3996. Creating and Sending Apple Events3-28
  3997. Creating an Apple Event Record3-29
  3998. Adding Apple Event Attributes and Parameters3-29
  3999. Sending an Apple Event and Handling the Reply3-30
  4000. Working With Object Specifier Records3-32
  4001. Data Structures Within an Object Specifier Record3-34
  4002. The Classification of Apple Event Objects3-39
  4003. Object Classes3-39
  4004. Properties and Elements3-42
  4005. Finding Apple Event Objects3-46
  4006. About the Apple Event Manager3-48
  4007. Supporting Apple Events as a Server Application3-48
  4008. Supporting Apple Events as a Client Application3-49
  4009. Supporting Apple Event Objects3-49
  4010. Supporting Apple Event Recording3-50
  4011. Introduction to Apple Events
  4012. This chapter introduces Apple events and the Apple Event Manager. Later chapters describe how your application can use the Apple Event Manager to respond to and send Apple events, locate Apple event objects, and record Apple events.
  4013. The interapplication communication (IAC) architecture for Macintosh computers consists of five parts: the Edition Manager, the Open Scripting Architecture (OSA), the Apple Event Manager, the Event Manager, and the Program-to-Program Communications (PPC) Toolbox. The chapter “Introduction to Interapplication Communication” in this book provides an overview of the relationships among these parts. 
  4014. The Apple Event Registry: Standard Suites defines both the actions performed by the standard Apple events, or “verbs,” and the standard Apple event object classes, which can be used to create “noun phrases” describing objects on which Apple events act. If your application uses the Apple Event Manager to respond to some of these standard Apple events, you can make it scriptable—that is, capable of responding to scripts written in a scripting language such as AppleScript. In addition, your application can use the Apple Event Manager to create and send Apple events and to allow user actions in your application to be recorded as Apple events.
  4015. Before you use this chapter or any of the other chapters about the Apple Event Manager, you should be familiar with the chapters “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials and “Process Manager” in Inside Macintosh: Processes. 
  4016. This chapter begins by describing Apple events and some of the data structures they contain. The rest of the chapter introduces the use of the Apple Event Manager to
  4017. n    respond to Apple events
  4018. n    send Apple events to request services or information
  4019. n    work with object specifier records
  4020. n    classify Apple event objects 
  4021. n    locate Apple event objects
  4022. Finally, this chapter summarizes the tasks you can perform with the Apple Event Manager and explains where to locate information you need to perform those tasks.
  4023.  
  4024. About Apple Events
  4025.  
  4026. An Apple event is a high-level event that conforms to the Apple Event Interprocess Messaging Protocol. The Apple Event Manager uses the services of the Event Manager to send Apple events between applications on the same computer, between applications on remote computers, or from an application to itself.
  4027. Applications typically use Apple events to request services and information from other applications or to provide services and information in response to such requests. Communication between two applications that support Apple events is initiated by a client application, which sends an Apple event to request a service or information. The application providing the service or the requested information is called a server application. The client and server applications can reside on the same local computer or on remote computers connected to a network. An application can also send Apple events to itself, thus acting as both client and server.   
  4028. Figure 3-1 shows a common Apple event, the Open Documents event. The Finder is the client; it requests that the SurfWriter application open the documents named “Dec. Invoice” and “Nov. Invoice.” The SurfWriter application responds to the Finder’s request by opening windows for the specified documents.
  4029. Figure 3-1    An Open Documents event
  4030.  
  4031. The Finder is considered the client application for the Open Documents event shown in Figure 3-1 because the Finder initiates the request for a service. The Finder can also be considered the source application for the same Open Documents event. A source application for an Apple event is one that sends an Apple event to another application or to itself. Similarly, the SurfWriter application can be described as either the server application or the target application for the Open Documents event shown in Figure 3-1. A target application for an Apple event is the one addressed to receive the Apple event. The terms client application and source application are not always synonymous, nor are the terms server application and target application. Typically, an Apple event client application sends an Apple event requesting a service to an Apple event server application; 
  4032. in this case, the server application is the target application for the Apple event. A server application may return information to the client in a reply Apple event—in which case, the client application is the target application for the reply.  
  4033. To perform the requested service—that is, to open the specified documents—the SurfWriter application shown in Figure 3-1 first uses the Apple Event Manager to identify the event (the Open Documents event) and to dispatch the event to SurfWriter’s handler for that Apple event. An Apple event handler is an application-defined function that extracts pertinent data from an Apple event, performs the requested action, and (usually) returns a result. In this case, SurfWriter’s Open Documents event handler examines the Apple event to determine which documents to open (Dec. Invoice and Nov. Invoice), then opens them as requested. 
  4034. To identify Apple events and respond appropriately, every application can rely on a vocabulary of standard Apple events that developers and Apple have established for all applications to use. These events are defined in the Apple Event Registry: Standard Suites. The standard suites, or groups of related Apple events that are usually implemented together, include the Required suite, the Core suite, and functional-area suites such as the Text suite and the Database suite. To function as a server application, your application should be able to respond to all the Apple events in the Required suite and any of those in the Core and functional-area suites that it is likely to receive. For example, most word-processing applications should be capable of responding to the Apple events in the Text suite, and most database applications should be capable of responding to those in the Database suite. 
  4035. If necessary, you can extend the definitions of the standard Apple events to match specific capabilities of your application. You can also define your own custom Apple events; however, before defining custom events, you should check with the Apple Event Registrar to find out whether you can adapt existing Apple event definitions or definitions still under development to the needs of your application. 
  4036. By supporting the standard Apple events in your application, you ensure that your application can communicate effectively with other applications that also support them. Instead of supporting many different custom events for a limited number of applications, you can support a relatively small number of standard Apple events that can be used by any number of applications. 
  4037. You can begin supporting Apple events by making your application a reliable server application: first for the required Apple events, then for the core and functional-area Apple events as appropriate. Once your application can respond to the appropriate standard Apple events, you can make it scriptable, or capable of responding to instructions written in a system-wide scripting language such as AppleScript. If necessary, your application can also send Apple events to itself or to other applications.
  4038. “About the Apple Event Manager,” which begins on page 3-48, provides more information about the steps you need to take to support Apple events in your application. 
  4039. The next section, “Apple Events and Apple Event Objects,” describes how Apple events can describe data and other items within an application or its documents. Subsequent sections describe the basic organization of Apple events and the data structures from which they are constructed. 
  4040. Apple Events and Apple Event Objects
  4041.  
  4042. The Open Documents event shown in Figure 3-1, like the other three required events, specifies an action and the applications or documents to which that action applies. The Apple Event Registry: Standard Suites provides a vocabulary of actions for use by all applications. In addition to a vocabulary of actions, effective communication between applications requires a method of referring to windows, data (such as words or graphic elements), files, folders, volumes, zones, and other discrete items on which actions can be performed. The Apple Event Manager includes routines that allow any application to construct or interpret “noun phrases” that describe the objects on which Apple events act.
  4043. Most of the Apple event definitions in the Apple Event Registry: Standard Suites include definitions of Apple event object classes, which are simply names for objects that can be acted upon by each kind of Apple event. An Apple event object is any distinct item supported by an application that can be described within an Apple event. Apple event objects can be anything that an application can locate on the basis of such a description, including items that a user can differentiate and manipulate while using an application, such as words, paragraphs, shapes, windows, or style formats. 
  4044. The definition for each Apple event object class in the Apple Event Registry: Standard Suites determines only how that kind of Apple event object should be described within an Apple event, not how it should be represented internally by an individual application. You do not have to write your application in an object-oriented programming language to support Apple event objects. Instead, you need to organize your application so that it can interpret a request for specific Apple event objects, locate the objects, and perform the requested action on them.
  4045. Figure 3-2 shows a common Apple event, the Get Data event from the Core suite. In this example, the SurfCharter application is the client application; it requests data contained in a specific table in a SurfWriter document. To obtain the data it wants, the SurfCharter application must include a description of the data in the Get Data event it sends to SurfWriter. This description identifies the requested data as an Apple event object called a table. The table is named “Summary of Sales” and is located in a document named “Sales Report.” 
  4046. The SurfWriter application’s Get Data handler extracts information about the request, locates the specified table, and returns a result. The Apple Event Manager provides a reply Apple event to which the SurfWriter application adds the requested information in the form requested by the Get Data event. The Apple Event Manager sends the reply event back to the SurfCharter application, which can use the requested data in whatever way is appropriate—in this case, displaying it as a pie chart.
  4047. Figure 3-2    A Get Data event
  4048.  
  4049. Apple Event Attributes and Parameters
  4050.  
  4051. When an application creates and sends an Apple event, the Apple Event Manager uses arguments passed to Apple Event Manager routines to construct the data structures that make up the Apple event. An Apple event consists of attributes (which identify the Apple event and denote its task) and, often, parameters (which contain information to be used by the target application). 
  4052. An Apple event attribute is a record that identifies the event class, event ID, target application, or some other characteristic of an Apple event. Taken together, the attributes of an Apple event denote the task to be performed on any data specified in the Apple event’s parameters. A client application can use Apple Event Manager routines to add attributes to an Apple event. After receiving an Apple event, a server application can use Apple Event Manager routines to extract and examine its attributes. 
  4053. An Apple event parameter is a record containing data that the target application uses. Unlike Apple event attributes (which contain information that can be used by both the Apple Event Manager and the target application), Apple event parameters contain data used only by the target application. For example, the Apple Event Manager uses the event class and event ID attributes to identify the server application’s handler for a specific Apple event, and the server application must have a handler to process the event identified by those attributes. By comparison, the list of documents contained in a parameter to an Open Documents event is used only by the server application. As with attributes, a client application can use Apple Event Manager routines to add parameters to an Apple event, and a server application can use Apple Event Manager routines to extract and examine the parameters of an Apple event it has received.
  4054. Note that Apple event parameters are different from the parameters of Apple Event Manager functions. Apple event parameters are records used by the Apple Event Manager; function parameters are arguments you pass to the function or that the function returns to you. You can specify both Apple event parameters and Apple event attributes in parameters to Apple Event Manager functions. For example, the AEGetParamPtr function uses a buffer to return the data contained in an Apple event parameter. You can specify the Apple event parameter whose data you want in one of the parameters of the AEGetParamPtr function.
  4055. Apple Event Attributes
  4056.  
  4057. Apple events are identified by their event class and event ID attributes. The event class is the attribute that identifies a group of related Apple events. The event class appears in the message field of the event record for an Apple event. For example, the four required Apple events have the value 'aevt' in the message fields of their event records. The value 'aevt' can also be represented by the kCoreEventClass constant. Several event classes are shown here:
  4058. Event class    Value    Description    
  4059. kCoreEventClass    'aevt'    A required Apple event    
  4060. kAECoreSuite    'core'    A core Apple event    
  4061. kAEFinderEvents    'FNDR'    An event that the Finder accepts    
  4062. kSectionEventMsgClass    'sect'    An event sent by the Edition Manager    
  4063.  
  4064. The event ID is the attribute that identifies the particular Apple event within its event class. In conjunction with the event class, the event ID uniquely identifies the Apple event and communicates what action the Apple event should perform. (The event IDs appear in the where field of the event record for an Apple event. For more information about event records, see the chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials.) For example, the event ID of an Open Documents event has the value 'odoc' (which can also be represented by the kAEOpenDocuments constant). The kCoreEventClass constant in combination with the kAEOpenDocuments constant identifies the Open Documents event to the Apple Event Manager.
  4065. Here are the event IDs for the four required Apple events:
  4066. Event ID    Value    Description    
  4067. kAEOpenApplication    'oapp'    Perform tasks required when a user opens your application without opening or printing any documents    
  4068. kAEOpenDocuments    'odoc'    Open documents    
  4069. kAEPrintDocuments    'pdoc'    Print documents    
  4070. kAEQuitApplication    'quit'    Quit your application    
  4071.  
  4072. In addition to the event class and event ID attributes, every Apple event must include an attribute that specifies the target application’s address. Remember that the target application is the one addressed to receive the Apple event. Your application can send an Apple event to itself or to another application (on the same computer or on a remote computer connected to the network).
  4073. Every Apple event must include event class, event ID, and target address attributes. Some Apple events can include other attributes; see “Keyword-Specified Descriptor Records,” which begins on page 3-15, for a complete list.
  4074. Apple Event Parameters
  4075.  
  4076. As with attributes, there are various kinds of Apple event parameters. A direct parameter usually specifies the data to be acted upon by the target application. For example, the direct parameter of the Print Documents event contains a list of documents. Some Apple events also take additional parameters, which the target application uses in addition to the data specified in the direct parameter. Thus, an Apple event for arithmetic operations might include additional parameters that specify operands in an equation. 
  4077. The Apple Event Registry: Standard Suites describes all parameters as either required or optional. A required parameter is one that must be present for the target application to carry out the task denoted by the Apple event. An optional parameter is a supplemental Apple Event parameter that also can be used to specify data to the target application. Optional parameters need not be included in an Apple event; default values for optional parameters are part of the event definition. The target application that handles the event must supply default values if the optional parameters are omitted.  
  4078. Direct parameters are usually defined as required parameters in the Apple Event Registry: Standard Suites; additional parameters may be defined as either required or optional. However, the Apple Event Manager does not enforce the definitions of required and optional events. Instead, the source application specifies, when it sends the event, which Apple event parameters the target can treat as if they were optional.
  4079. For more information about optional parameters, see “Specifying Optional Parameters for an Apple Event,” which begins on page 5-7.
  4080. Interpreting Apple Event Attributes and Parameters
  4081.  
  4082. Figure 3-3 shows the major Apple event attributes and direct parameter for the Open Documents event introduced in Figure 3-1.
  4083. Figure 3-3    Major attributes and direct parameter of an Open Documents event
  4084.  
  4085. When the SurfWriter application receives any high-level event, it calls the AEProcessAppleEvent function to process the event. For an Apple event such as the Open Documents event shown in Figure 3-3, the AEProcessAppleEvent function uses the event class and event ID attributes to dispatch the event to the SurfWriter application’s Open Documents handler. In response, the Open Documents handler opens the documents specified in the direct parameter. 
  4086. The definition of a given Apple event in the Apple Event Registry: Standard Suites suggests how the source application can organize the data in the Apple event’s parameters and how the target application interprets that data. The data in an Apple event parameter may use standard or private data types and may include a description of an Apple event object. Each Apple event handler provided by an application should be written with the format of the expected data in mind.
  4087. Apple events can use standard data types, such as strings of text, long integers, Boolean values, and alias records, for the corresponding data in Apple event parameters. For example, the Get Data event can contain an optional parameter specifying the form in which the requested data should be returned. This optional parameter always consists of a list of four-character codes denoting desired descriptor types in order of preference. Apple events can also use special data types defined by the Apple Event Manager. 
  4088. Apple event parameters often contain descriptions of Apple event objects. These descriptions make use of a standard classification scheme summarized in “The Classification of Apple Event Objects,” which begins on page 3-39.
  4089. For example, every Get Data event includes a required parameter that describes the Apple event object containing the data requested by the client application. Thus, one application can send a Get Data event to another application, requesting, for instance, one paragraph of a document, the first and last paragraphs of a document, all pictures in the document, all paragraphs containing the word “sales,” or pages 10 through 12 of the document. 
  4090. Figure 3-4 shows the Apple event attributes and direct parameter for the Get Data event introduced in Figure 3-2. The direct parameter for the Get Data event sent by the SurfCharter application describes the requested Apple event object as a table called “Summary of Sales” in the document “Sales Report.” Both the table and the document are Apple event objects. The description of an Apple event object always includes a description of its location. In most cases, Apple event objects are located inside other Apple event objects.
  4091. Figure 3-4    Major attributes and direct parameter of a Get Data event
  4092.  
  4093. To process the information in the Get Data event, the SurfWriter application calls the AEProcessAppleEvent function. The AEProcessAppleEvent function uses the event class and event ID attributes to dispatch the event to the SurfWriter application’s handler for the Get Data Apple event. The SurfWriter application responds to the Get Data event by resolving the description of the Apple event object—that is, by using the AEResolve function, other Apple Event Manager routines, and its own application-defined functions to locate the table named “Summary of Sales.” After locating the table, SurfWriter adds a copy of the table’s data to the reply event, which the Apple Event Manager then sends to the SurfCharter application. The SurfCharter application then displays the data in its active window.  
  4094. The next section, “Data Structures Within Apple Events,” describes the data structures the Apple Event Manager uses for Apple event attributes and parameters. 
  4095. Data Structures Within Apple Events
  4096.  
  4097. The Apple Event Manager constructs its own internal data structures to contain the information in an Apple event. Neither the sender nor the receiver of an Apple event should manipulate data directly after it has been added to an Apple event; each should rely on Apple Event Manager functions to do so. 
  4098. This section describes the most important data structures used by the Apple event Manager to construct Apple events. The first structure described is the descriptor record, a data structure of type AEDesc. Applications may access the data in an individual descriptor record directly if it is not part of another Apple Event Manager data structure. 
  4099. In some cases it is convenient for the Apple Event Manager to describe descriptor records by data types that indicate their contents; thus, it also defines data structures such as type AEAddressDesc, AEDescList, and AERecord, which are descriptor records used to hold addresses, lists of other descriptor records, and Apple event parameters, respectively. These and most of the other data structures described in this section are formally defined as data structures of type AEDesc; they differ only in the purposes for which they are used.
  4100. Descriptor Records
  4101.  
  4102. Descriptor records are the building blocks used by the Apple Event Manager to construct Apple event attributes and parameters. A descriptor record is a data structure of type AEDesc; it consists of a handle to data and a descriptor type that identifies the type of the data to which the handle refers.
  4103. TYPE AEDesc = 
  4104. RECORD                                            {descriptor record}
  4105.     descriptorType:                        DescType;                {type of data}
  4106.     dataHandle:                         Handle        ;        {handle to data}
  4107. END;
  4108. If a descriptor record exists separately from other Apple Event Manager data structures, it is possible to retrieve the data associated with its handle by dereferencing the handle twice. After a descriptor record has been added to any other Apple Event Manager data structure, you must use Apple Event Manager routines to extract data from the descriptor record.
  4109. The descriptor type is a structure of type DescType, which in turn is of data type ResType—that is, a four-character code. Constants are usually used in place of these four-character codes when referring to descriptor types. Descriptor types represent various data types. Here are some of the major descriptor type constants, their values, and the kinds of data they identify.
  4110. Descriptor type    Value    Description of data    
  4111. typeBoolean    'bool'    1-byte Boolean value    
  4112. typeChar    'TEXT'    Unterminated string    
  4113. typeLongInteger    'long'    32-bit integer    
  4114. typeShortInteger    'shor'    16-bit integer    
  4115. typeMagnitude    'magn'    Unsigned 32-bit integer    
  4116. typeAEList    'list'    List of descriptor records    
  4117. typeAERecord    'reco'    List of keyword-specified descriptor records    
  4118. typeAppleEvent    'aevt'    Apple event record    
  4119. typeEnumerated    'enum'    Enumerated data    
  4120. typeType    'type'    Four-character code     
  4121. typeFSS    'fss '    File system specification    
  4122. typeKeyword    'keyw'    Apple event keyword    
  4123. typeNull    'null'    Nonexistent data (handle whose value is NIL)    
  4124.  
  4125. For a complete list of the basic descriptor types used by the Apple Event Manager, see Table 4-2 on page 4-57.
  4126. Figure 3-5 illustrates the logical arrangement of a descriptor record with a descriptor type of typeChar, which specifies that the data handle refers to an unterminated string (in this case, the text “Summary of Sales”).
  4127. Figure 3-5    A descriptor record whose data handle refers to an unterminated string
  4128.  
  4129. Figure 3-6 illustrates the logical arrangement of a descriptor record with a descriptor type of typeType, which specifies that the data handle refers to a four-character code (in this case the constant kCoreEventClass, whose value is 'aevt'). This descriptor record can be used in an Apple event attribute that identifies the event class for any Apple event in the Core suite. 
  4130. Figure 3-6    A descriptor record whose data handle refers to event class data
  4131.  
  4132. Every Apple event includes an attribute specifying the address of the target application. A descriptor record that contains an application’s address is called an address descriptor record.
  4133. TYPE        AEAddressDesc = AEDesc;                                        {address descriptor record}
  4134. The address in an address descriptor record can be specified as one of these four basic types (or as any other descriptor type you define that can be coerced to one of these types):
  4135. Descriptor type    Value    Description    
  4136. typeApplSignature    'sign'    Application signature    
  4137. typeSessionID    'ssid'    Session reference number    
  4138. typeTargetID    'targ'    Target ID record    
  4139. typeProcessSerialNumber    'psn '    Process serial number    
  4140.  
  4141. Like several of the other data structures defined by the Apple Event Manager for use in Apple event attributes and Apple event parameters, an address descriptor record is identical to a descriptor record of data type AEDesc; the only difference is that the data for an address descriptor record must always consist of an application’s address.   
  4142. Keyword-Specified Descriptor Records
  4143.  
  4144. After the Apple Event Manager has assembled the necessary descriptor records as the attributes and parameters of an Apple event, your application cannot examine the contents of the Apple event directly. Instead, your application must use Apple Event Manager routines to request each attribute and parameter by keyword. Keywords are arbitrary names used by the Apple Event Manager to keep track of various descriptor records. The AEKeyword data type is defined as a four-character code.
  4145. TYPE        AEKeyword = PACKED ARRAY[1..4] OF Char;                                                     {keyword for a }
  4146.                                                              { descriptor record}
  4147. Constants are typically used for keywords. Here is a list of the keyword constants for Apple event attributes:
  4148. Attribute keyword    Value    Description    
  4149. keyAddressAttr     'addr'    Address of target or client application      
  4150. keyEventClassAttr     'evcl'    Event class of Apple event     
  4151. keyEventIDAttr    'evid'    Event ID of Apple event     
  4152. keyEventSourceAttr    'esrc'    Nature of the source application    
  4153. keyInteractLevelAttr    'inte'    Settings for allowing the Apple Event Manager to bring a server application to the foreground, if necessary, to interact with the user     
  4154. keyMissedKeywordAttr    'miss'    Keyword for first required parameter remaining in an Apple event     
  4155. keyOptionalKeywordAttr    'optk'    List of keywords for parameters of the Apple event that should be treated as optional by the target application    
  4156. keyOriginalAddressAttr    'from'    Address of original source of Apple event if the event has been forwarded (available only in version 1.01 or later versions of the Apple Event Manager)      
  4157. keyReturnIDAttr     'rtid'    Return ID for reply Apple event     
  4158. keyTimeoutAttr    'timo'    Length of time, in ticks, that the client will wait for a reply or a result from the server     
  4159. keyTransactionIDAttr    'tran'    Transaction ID identifying a series of Apple events     
  4160.  
  4161. Here is a list of the keyword constants for commonly used Apple event parameters:
  4162. Parameter keyword    Value    Description    
  4163. keyDirectObject    '----'    Direct parameter     
  4164. keyErrorNumber    'errn'    Error number parameter    
  4165. keyErrorString    'errs'    Error string parameter    
  4166.  
  4167. The Apple Event Registry: Standard Suites defines additional keyword constants for Apple event parameters that can be used with specific Apple events. 
  4168. The Apple Event Manager associates keywords with specific descriptor records by means of a keyword-specified descriptor record, a data structure of type AEKeyDesc that consists of a keyword and a descriptor record. 
  4169. TYPE        AEKeyDesc =     {keyword-specified descriptor record}
  4170. RECORD
  4171.     descKey:                    AEKeyword;                    {keyword}
  4172.     descContent:                    AEDesc;                    {descriptor record}
  4173. END;
  4174. Figure 3-7 illustrates a keyword-specified descriptor record with the keyword keyEventClassAttr—the keyword that identifies an event class attribute. The figure shows the logical arrangement of the event class attribute for the Open Documents event shown in Figure 3-3 on page 3-10. The descriptor record in Figure 3-7 is identical to the one in Figure 3-6; its descriptor type is typeType, and the data to which its handle refers identifies the event class as kCoreEventClass. 
  4175. Figure 3-7    A keyword-specified descriptor record for the event class attribute of an Open Documents event
  4176.  
  4177. Descriptor Lists
  4178.  
  4179. When extracting data from an Apple event, you use Apple Event Manager functions to copy data to a buffer specified by a pointer, or to return a descriptor record whose data handle refers to a copy of the data, or to return lists of descriptor records (called descriptor lists). 
  4180. As previously noted, the descriptor record (of data type AEDesc) is the fundamental structure in Apple events, and it consists of a descriptor type and a handle to data. A descriptor list is a data structure of type AEDescList defined by the data type AEDesc—that is, a descriptor list is a descriptor record whose data handle refers to a list of other descriptor records (unless it is an empty list).
  4181. TYPE        AEDescList = AEDesc;                                    {list of descriptor records}
  4182. Like several other Apple Event Manager data structures, a descriptor list is identical to a descriptor record of data type AEDesc; the only difference is that the data in a descriptor list must always consist of a list of other descriptor records. 
  4183. Figure 3-8 illustrates the logical arrangement of the descriptor list that specifies the direct parameter of the Open Documents event shown in Figure 3-3 on page 3-10. This descriptor list consists of a list of descriptor records that contain alias records to filenames. (See the chapter “Alias Manager” in Inside Macintosh: Files for a detailed description of alias records.)
  4184. Figure 3-8    A descriptor list for a list of aliases
  4185.  
  4186. The descriptor list in Figure 3-8 provides the data for a keyword-specified descriptor record. Keyword-specified descriptor records for Apple event parameters can in turn be combined in an AE record, which is a descriptor list of data type AERecord.
  4187. TYPE        AERecord = AEDescList;                                        {list of keyword-specified }
  4188.                                                 { descriptor records}
  4189. The handle for a descriptor list of data type AERecord refers to a list of keyword-specified descriptor records that can be used to construct Apple event parameters. The Apple Event Manager provides routines that allow your application to create AE records and extract data from them when creating or responding to Apple events. 
  4190. An AE record has the descriptor type typeAERecord and can be coerced to several other descriptor types. An Apple event record, which is different from an AE record, is another special descriptor list of data type AppleEvent and descriptor type typeAppleEvent.
  4191. TYPE        AppleEvent = AERecord;                                        {list of attributes and     }
  4192.                                                 { parameters necessary for }
  4193.                                                 { an Apple event}
  4194. An Apple event record describes a full-fledged Apple event. Like the data for an AE record, the data for an Apple event record consists of a list of keyword-specified descriptor records. Unlike an AE record, the data for an Apple event record is divided into two parts, one for attributes and one for parameters. This division within the Apple event record allows the Apple Event Manager to distinguish between an Apple event’s attributes and its parameters. 
  4195. Descriptor lists, AE records, and Apple event records are all descriptor records whose handles refer to a nested list of other descriptor records. The data associated with each data type may be organized differently and is used by the Apple Event Manager for different purposes. In each case, however, the data is identified by a handle in a descriptor record. This means that you can pass an Apple event record to any Apple Event Manager function that expects an AE record. Similarly, you can pass Apple event records and AE records, as well as descriptor lists and descriptor records, to any Apple Event Manager functions that expect records of data type AEDesc.
  4196. When you use the AECreateAppleEvent function, the Apple Event Manager creates an Apple event record containing the attributes for an Apple event’s event class, event ID, target address, return ID, and transaction ID. You then use Apple Event Manager functions such as AEPutParamDesc and AEPutAttributeDesc to add or modify attributes and to add any necessary parameters to the Apple event. 
  4197. Figure 3-9 shows an example of a complete Apple event—a data structure of type AppleEvent containing a list of keyword-specified descriptor records that name the attributes and parameters of an Open Documents event. The figure includes the event class attribute shown in Figure 3-7 and the descriptor list shown in Figure 3-8, which forms the direct parameter—the keyword-specified descriptor record with the keyword keyDirectObject. The entire figure corresponds to the Open Documents event shown in Figure 3-3 on page 3-10.
  4198. The next two sections, “Responding to Apple Events” and “Creating and Sending Apple Events,” provide a quick overview of the steps your application must take to respond to and send Apple events.
  4199. Figure 3-9    Data structures within an Open Documents event
  4200.  
  4201.  
  4202.  
  4203. Responding to Apple Events
  4204.  
  4205. A client application typically uses the Apple Event Manager to create and send an Apple event requesting a service or information. A server application responds by using the Apple Event Manager to process the Apple event, extract data from the attributes and parameters of the Apple event, and if necessary add requested data to the reply event returned by the Apple Event Manager to the client application. The server usually provides its own Apple event handler for performing the action requested by the client’s Apple event. 
  4206. As its first step in supporting Apple events, your application should support the required Apple events sent by the Finder. If you plan to implement publish and subscribe capabilities, your application must also respond to the Apple events sent by the Edition Manager. Your application should also be able to respond to the standard Apple events that other applications are likely to send to it or that it can send to itself. This section provides a quick overview of the tasks your application must perform in responding to Apple events.
  4207. To respond to Apple events, your application must
  4208. n    set the appropriate flags in its 'SIZE' resource
  4209. n    test for high-level events in its event loop
  4210. n    provide Apple event handlers for the Apple events it supports
  4211. n    use the AEInstallEventHandler function to install its Apple event handlers
  4212. n    use the AEProcessAppleEvent function to process Apple events
  4213. Before your application can respond to Apple events sent from remote computers, the user of your application must allow network users to link to your application. To do this, the user selects your application in the Finder, chooses Sharing from the File menu, and then clicks the Allow Remote Program Linking checkbox. If the user has not yet started program linking, the Sharing command offers to display the Sharing Setup control panel so that the user can start program linking. The user must also authorize remote users for program linking by using the Users & Groups control panel. Program linking and setting up authenticated sessions are described in the chapter “Program-to-Program Communications Toolbox” in this book.
  4214. Accepting and Processing Apple Events
  4215.  
  4216. To accept or send Apple events (or any other high-level events), you must set the appropriate flags in your application’s 'SIZE' resource and include code to handle high-level events in your application’s main event loop. 
  4217. Two flags in the 'SIZE' resource determine whether an application receives high-level events: 
  4218. n    The isHighLevelEventAware flag must be set for your application to receive any high-level events.
  4219. n    The localAndRemoteHLEvents flag must be set for your application to receive high-level events sent from another computer on the network.
  4220. An Apple event (like all high-level events) is identified by a message class of kHighLevelEvent in the what field of the event record. You test the what field of the event record to determine whether it contains the value represented by the kHighLevelEvent constant; if your application defines any high-level events other than Apple events, you should also test the message field of the event record to determine whether the high-level event is something other than an Apple event. If the high-level event is not one that you’ve defined for your application, assume that it is an Apple event. (You are encouraged to use Apple events instead of defining your own high-level events whenever possible.)
  4221. After determining that an event is an Apple event, use the AEProcessAppleEvent function to let the Apple Event Manager identify the event. Figure 3-10 shows how the SurfWriter application accepts and begins to process an Apple event sent by the Finder.
  4222. Figure 3-10    Accepting and processing an Open Documents event
  4223.  
  4224. The AEProcessAppleEvent function first identifies the Apple event by examining the data in the event class and event ID attributes. The function then uses that data to call the Apple event handler that your application provides for that event. The Apple event handler extracts the pertinent data from the Apple event, performs the requested action, and returns a result. For example, if the event has an event class of kCoreEventClass and an event ID of kAEOpenDocuments, the AEProcessAppleEvent function calls your application’s handler for the Open Documents event. 
  4225. Before your application attempts to accept or process any Apple events, it must use the AEInstallEventHandler function to install Apple event handlers. This function installs handlers in an Apple event dispatch table for your application; the Apple Event Manager uses this table to map Apple events to handlers in your application. When your application calls the AEProcessAppleEvent function to process an Apple event, the Apple Event Manager checks the Apple event dispatch table and, if your application has installed a handler for that Apple event, calls that handler. Figure 3-11 shows how the flow of control passes from your application to the Apple Event Manager and back to your application.
  4226. Figure 3-11    The Apple Event Manager calling the handler for an Open Documents event
  4227.  
  4228. About Apple Event Handlers
  4229.  
  4230. Your Apple event handlers must generally perform the following tasks:
  4231. n    extract the parameters and attributes from the Apple event
  4232. n    check that all the required parameters have been extracted
  4233. n    locate any Apple event objects specified by object specifier records in the Apple event parameters
  4234. n    if your application needs to interact with the user, use the AEInteractWithUser function to bring it to the foreground
  4235. n    perform the action requested by the Apple event
  4236. n    dispose of any copies of descriptor records that have been created
  4237. n    add information to the reply Apple event if requested
  4238. This section describes how your application’s Apple event handlers can use the Apple Event Manager to accomplish some of these tasks. The chapter “Responding to Apple Events” in this book provides detailed information about handling Apple events and interacting with the user.
  4239. Extracting and Checking Data
  4240.  
  4241. You must use Apple Event Manager functions to extract the data from Apple events. You can also use Apple Event Manager functions to extract data from descriptor records, descriptor lists, and AE records. Most of these routines are available in two forms: they either return a copy of the data in a buffer or return a copy of the descriptor record for the data, including a copy of the data. 
  4242. The following list shows the main functions you can use to access the data of an Apple event:
  4243. Function    Description(continued)    
  4244. AEGetParamPtr    Uses a buffer to return a copy of the data contained in an Apple event parameter. Usually used to extract data of fixed length or known maximum length; for example, to extract the result code from the keyErrorNumber parameter of a reply Apple event.    
  4245. AEGetParamDesc    Returns a copy of the descriptor record or descriptor list for an Apple event parameter. Usually used to extract data of variable length; for example, to extract the descriptor list for a list of alias records specified in the direct parameter of the Open Documents event.    
  4246. AEGetAttributePtr    Uses a buffer to return a copy of the data contained in an Apple event attribute. Used to extract data of fixed length or known maximum length; for example, to determine the source of an Apple event by extracting the data from the keyEventSourceAttr attribute.    
  4247.     
  4248. continued    
  4249. AEGetAttributeDesc    Returns a copy of the descriptor record for an attribute. Used to extract data of variable length; for example, to make a copy of a descriptor record containing the address of an application.    
  4250. AECountItems    Returns the number of descriptor records in a descriptor list. Used, for example, to determine the number of alias records for documents specified in the direct parameter of the 
  4251. Open Documents event.    
  4252. AEGetNthPtr    Uses a buffer to return a copy of the data for a descriptor record contained in a descriptor list. Used to extract data of fixed length or known maximum length; for example, to extract the name and location of a document from the descriptor list specified in the direct parameter of the 
  4253. Open Documents event.    
  4254. AEGetNthDesc    Returns a copy of a descriptor record from a descriptor list. Used to extract data of variable length; for example, to get the descriptor record containing an alias record from the list specified in the direct parameter of the Open Documents event.    
  4255.  
  4256. You can specify the descriptor type of the resulting data for these functions; if this type is different from the descriptor type of the attribute or parameter, the Apple Event Manager attempts to coerce it to the specified type. In the direct parameter of the Open Documents event, for example, each descriptor record in the descriptor list is an alias record; each alias record specifies a document to be opened. As explained in the chapter “Introduction to File Management” of Inside Macintosh: Files, all your application usually needs is the file system specification (FSSpec) record of the document. When you extract the descriptor record from the descriptor list, you can request that the Apple Event Manager return the data to your application as a file system specification record instead of an alias record.
  4257. After extracting all known Apple event parameters, your handler should check that it retrieved all the parameters that the source application considered to be required. To do so, determine whether the keyMissedKeywordAttr attribute exists. If so, your handler has not retrieved all the required parameters, and it should return an error.
  4258. Although the Apple Event Registry: Standard Suites defines Apple event parameters as either required or optional, the Apple Event Manager does not enforce the definitions of required and optional events. Instead, the source application specifies, when it sends the event, which Apple event parameters the target can treat as if they were optional. For more information about optional parameters, see “Specifying Optional Parameters for an Apple Event,” which begins on page 5-7.
  4259. If any of the Apple event parameters include object specifier records, your handler should use the AEResolve function, other Apple Event Manager routines, and your own application-defined functions to locate the corresponding Apple event objects. For more information about locating Apple event objects, see “Working With Object Specifier Records,” which begins on page 3-32.
  4260. Interacting With the User
  4261.  
  4262. In some cases, the server may need to interact with the user when it handles an Apple event. For example, your handler for the Print Documents event may need to display a print options dialog box and get settings from the user before printing. By specifying flags to the AESetInteractionAllowed function, you can set preferences to allow user interaction with your application (a) only when your application is sending the Apple event to itself, (b) only when the client application is on the same computer as your application, or (c) for any event sent by any client application on any computer. In addition, your handler should always use the AEInteractWithUser function before displaying a dialog box or alert box or otherwise interacting with the user. The AEInteractWithUser function determines whether user interaction can occur and takes appropriate action depending on the circumstances.
  4263. Both the client and server specify their preferences for user interaction: the client specifies whether the server should be allowed to interact with the user, and the server specifies when it allows user interaction while processing an Apple event. The Apple Event Manager does not allow a server application to interact with the user in response to a client application’s Apple event unless at least two conditions are met: First, the client application must set flags in the sendMode parameter of the AESend function indicating that user interaction is allowed. Second, the server application must either set no user interaction preferences, in which case AEInteractWithUser assumes that only interaction with a client on the local computer is allowed; or it must set flags to the AESetInteractionAllowed function indicating that user interaction is allowed. 
  4264. If these two conditions are met and if AEInteractWithUser determines that both the client and server applications allow user interaction under the current circumstances, AEInteractWithUser brings your application to the foreground if it isn’t already in the foreground. Your application can then display its dialog box or alert box or otherwise interact with the user. The AEInteractWithUser function brings your server application to the front either directly or after the user responds to a notification request.
  4265. For detailed information about how to specify flags to the AESetInteractionAllowed function and how the Apple Event Manager determines whether user interaction is allowed, see the section 
  4266. “Interacting With the User,” which begins on page 4-45.
  4267. Performing the Requested Action and Returning a Result
  4268.  
  4269. When your application responds to an Apple event, it should perform the standard action requested by that event. For example, your application should respond to the Open Documents event by opening the specified documents in titled windows just as if the user had selected each document from the Finder and then chosen Open from the File menu. 
  4270. Many Apple events can ask your application to return data. For instance, if your application is a spelling checker, the client application might expect your application to return data in the form of a list of misspelled words. Figure 3-14 on page 3-38 shows a similar example: a Get Data event that asks the server application to locate a specific Apple event object and return the data associated with it. 
  4271. If the client application requests a reply, the Apple Event Manager prepares a reply Apple event by passing a default reply Apple event to your handler. If the client application does not request a reply, the Apple Event Manager passes a null descriptor record—that is, a descriptor record of type typeNull whose data handle has the value NIL—to your handler instead of a default reply Apple event. The default reply Apple event has no parameters when it is passed to your handler, but your handler can add parameters to it. If your application is a spelling checker, for example, you can return a list of misspelled words in a parameter. However, your handler should check whether the reply Apple event exists before attempting to add any attributes or parameters to it. Any attempt to add an Apple event attribute or parameter to a null descriptor record generates an error. 
  4272. When you extract a descriptor record using the AEGetParamDesc, AEGetAttributeDesc, AEGetNthDesc, or AEGetKeyDesc function, the Apple Event Manager creates a copy of the descriptor record for you to use. When your handler is finished using a copy of a descriptor record, you should dispose of it—and thereby deallocate the memory used by its data—by calling the AEDisposeDesc function.
  4273. Note
  4274. Outputs from functions such as AEGetKeyPtr and other routines whose names end in -Ptr use a buffer rather than a descriptor record to return data. Because these functions don’t require the use of AEDisposeDesc, it is preferable to use them for any data that is not identified by a handle.u
  4275. Your Apple event handler should always set its function result either to noErr if it successfully handles the Apple event or to a nonzero result code if an error occurs. If your handler returns a nonzero result code, the Apple Event Manager adds a keyErrorNumber parameter to the reply Apple event (unless you have already added a keyErrorNumber parameter). This parameter contains the result code that your handler returns. The client should check whether the keyErrorNumber parameter exists to determine whether your handler performed the requested action. In addition to returning a result code, your handler can also return an error string in the keyErrorString parameter of the reply Apple event. The client can use this string in an error message to the user.
  4276. If the client application requested a reply, the Apple Event Manager returns the reply Apple event, which is identified by the event class kCoreEventClass and by the event ID kAEAnswer. When the client has finished using the reply Apple event, it should dispose of both the reply event and the original event—and thereby deallocate the memory they use—by calling the AEDisposeDesc function. The Apple Event Manager takes care of disposing both the Apple event and the reply Apple event after a server application’s handler returns to AEProcessAppleEvent, but a server application is responsible for disposing of any Apple event data structures it creates while extracting data from the Apple event.
  4277. Figure 3-12 shows the entire process of responding to an Apple event. 
  4278. Figure 3-12    Responding to an Open Documents event  
  4279.  
  4280. When your handler returns a result code to the Apple Event Manager, you have finished your response to the client application’s Apple event.
  4281.  
  4282. Creating and Sending Apple Events
  4283.  
  4284. Your application can use Apple events to request services or information from other applications, send information to other applications, or trigger actions within your application. For example, you can use the core Apple event Get Data to request specific data from another application’s documents. Similarly, you can use other Apple events to request services—for example, asking a spell-checking application to check the text in a document created by your application. Consult the Apple Event Registry: Standard Suites for the format and function of the standard Apple events that you want your application to send. 
  4285. To communicate with another application by sending an Apple event, your application must
  4286. n    set the appropriate flags in its 'SIZE' resource
  4287. n    create an Apple event record by calling the AECreateAppleEvent function
  4288. n    use Apple Event Manager functions to add parameters and any additional attributes to the Apple event
  4289. n    call the AESend function to send the Apple event
  4290. n    dispose of any copies of descriptor records that you have created
  4291. n    handle the reply Apple event (if necessary)
  4292. The sections that follow describe how your application can use the Apple Event Manager to accomplish these tasks. The chapter “Creating and Sending Apple Events” in this book provides detailed information about creating and sending Apple events.
  4293. To act as a server for your application, the target application must support high-level events and must be running. The server can be your own application, another application running on the user’s computer, or an application running on another user’s computer connected to the network. 
  4294. Your application should also allow the user to choose among the various applications available as servers. The PPCBrowser function allows users to select target applications on their own computers or on computers connected to the network. The PPCBrowser function presents a standard user interface for choosing a target application, much as the Standard File Package provides a standard user interface for opening and saving files. See the chapter “Program-to-Program Communications Toolbox” in this book for details on using the PPCBrowser function.
  4295. If the server application is on a remote computer on a network, the user of that computer must allow program linking to the server application. The user of the server application does this by selecting the application icon in the Finder, choosing Sharing from the File menu, then clicking the Allow Remote Program Linking checkbox. If the user has not yet started program linking, the Sharing command offers to display the Sharing Setup control panel so that the user can start program linking. The user must also authorize remote users for program linking by using the Users & Groups control panel. Program linking and setting up authenticated sessions are described in the chapter “Program-to-Program Communications Toolbox” in this book.
  4296. Creating an Apple Event Record
  4297.  
  4298. Use the AECreateAppleEvent function to create an Apple event record. Using the arguments you pass to the AECreateAppleEvent function, the Apple Event Manager constructs the data structures describing the event class, the event ID, and the target address attributes of an Apple event. The event class and event ID, of course, identify the particular event you wish to send. The target address identifies the intended recipient of the Apple event.
  4299. You can specify two other attributes with the AECreateAppleEvent function: the reply ID and the transaction ID. For the reply ID attribute, you usually specify the kAutoGenerateReturnID constant to the AECreateAppleEvent function. This constant ensures that the Apple Event Manager generates a unique return ID for the reply Apple event returned from the server. For the transaction ID attribute, you usually specify the kAnyTransactionID constant, which indicates that this Apple event is not one of a series of interdependent Apple events.
  4300. Adding Apple Event Attributes and Parameters
  4301.  
  4302. The Apple event record created with the AECreateAppleEvent function serves as a foundation for the Apple event you want to send. Descriptor records and descriptor lists are the building blocks from which the complete Apple event record is constructed. To create descriptor records and descriptor lists and add items to a descriptor list, use the following functions:
  4303. Function    Description    
  4304. AECreateDesc    Takes a descriptor type and a pointer to data and converts them into a descriptor record    
  4305. AECreateList    Creates an empty descriptor list or AE record.    
  4306. AEPutPtr    Takes a descriptor type and a pointer to data and adds the data to a descriptor list as a descriptor record; used, for example, to add to a descriptor list a number used as the parameter of an Apple event requesting a calculation.    
  4307. AEPutDesc    Adds a descriptor record to a descriptor list; used, for example, to add to a descriptor list an alias record used as the direct parameter of an Apple event requesting file manipulation.    
  4308.  
  4309. To add the remaining attributes and parameters necessary for your Apple event to the Apple event record, you can use these additional Apple Event Manager functions:
  4310. Function    Description    
  4311. AEPutParamPtr    Takes a keyword, descriptor type, and pointer to data and adds the data to an Apple event record as a parameter with the specified keyword (replacing any existing parameter with the same keyword); used, for example, to put numbers into the parameters of an Apple event that asks the server to perform a calculation.    
  4312. AEPutParamDesc    Takes a keyword and a descriptor record and adds the descriptor record to an Apple event record as a parameter with the specified keyword (replacing any existing parameter with the same keyword); used, for example, to place a descriptor list containing alias records into the direct parameter of an Apple event that requests a server to manipulate files.    
  4313. AEPutAttributePtr    Takes a keyword, descriptor type, and pointer to data and adds the descriptor record to an Apple event record as an attribute with the specified keyword (replacing any existing attribute with the same keyword); used, for example, to change the transaction ID of an Apple event record that is waiting to be sent.     
  4314. AEPutAttributeDesc    Takes a keyword and a descriptor record and adds the descriptor record to an Apple event record as an attribute with the specified keyword (replacing any existing attribute with the same keyword); used, for example, to replace the descriptor record used for the target address attribute in an Apple event record waiting to be sent.    
  4315.  
  4316. Apple event parameters for core events and functional-area events can include descriptions of Apple event objects in special descriptor records called object specifier records. For an overview of object specifier records, see “Working With Object Specifier Records,” which begins on page 3-32.
  4317. Sending an Apple Event and Handling the Reply
  4318.  
  4319. After you add all the attributes and parameters required for the Apple event, use the AESend function to send the Apple event. The Apple Event Manager uses the Event Manager to transmit the Apple event to the server application.
  4320. The AESend function requires that you specify whether your application should wait for a reply from the server. If you specify that you want a reply, the Apple Event Manager prepares a reply Apple event for your application by passing a default reply Apple event to the server. The Apple Event Manager returns any nonzero result code from the server’s handler in the keyErrorNumber parameter of the reply Apple event. The server can return an error string in the keyErrorString parameter of the reply Apple event. The server can also use the reply Apple event to return any data you requested—for example, the results of a numeric calculation or a list of misspelled words.
  4321. You specify how your application should wait for a reply by using one of these flags in the sendMode parameter of the AESend function:
  4322. Flag    Description    
  4323. kAENoReply    Your application does not want a reply Apple event.    
  4324. kAEQueueReply    Your application wants a reply Apple event; the reply appears in your event queue as soon as the server has the opportunity to process and respond to your Apple event.    
  4325. kAEWaitReply    Your application wants a reply Apple event and is willing to give up the processor while waiting for the reply; for example, if the server application is on the same computer as your application, your application yields the processor to allow the server to respond to your Apple event.    
  4326.  
  4327. If you specify the kAEWaitReply flag, you should provide an idle function. This function should process any non-high-level events that occur while your application is waiting for a reply. You supply a pointer to your idle function as a parameter to the AESend function. So that your application can process other Apple events while it is waiting for a reply, you can also specify an optional filter function to the AESend function.
  4328. If you specify the kAENoReply flag, the reply Apple event prepared by the Apple Event Manager for the server application consists of a null descriptor record.
  4329. If your Apple event may require the user to interact with the server application (for example, to specify print or file options), you can communicate your user interaction preferences to the server by specifying additional flags in the sendMode parameter of the AESend function. These flags specify the conditions, if any, under which the server application can interact with the user and, if interaction is allowed, whether the server should come directly to the foreground or post a notification request.
  4330. The server application specifies its own preferences for user interaction by specifying flags to the AESetInteractionAllowed function, as described in the previous section. The interaction of the client and server applications’ preferences is explained in detail in “Interacting With the User,” which begins on page 4-45.
  4331. After you send an Apple event, your application is responsible for disposing of the Apple event record—and thereby deallocating the memory its data uses—by calling the AEDisposeDesc function. If you create one descriptor record and add it to another, the Apple Event Manager adds a copy of the newly created one to the existing one and also makes a copy of the associated data. For example, you might use the AECreateDesc function to create a descriptor record that you wish to add to an Apple event. When you use the AEPutParamDesc function, it adds a copy of your newly created descriptor record, including its data, as a parameter to an existing Apple event. When you no longer need the original descriptor record, you should call AEDisposeDesc to dispose of it.
  4332. Your application should dispose of all the descriptor records that are created for the purposes of adding parameters and attributes to an Apple event. You normally dispose of your Apple event and its reply after you receive a result from the AESend function. You should dispose of these even if AESend returns an error result. 
  4333. If you specify the kAEWaitReply flag, the reply Apple event is returned in a parameter you pass to the AESend function. If you specify the kAEQueueReply flag to the AESend function, the reply Apple event is returned in the event queue. In this case, the reply is identified by the event class kCoreEventClass and the event ID kAEAnswer. Your application processes reply events in its event queue in the same way that server applications process Apple events. 
  4334. Your application should check for the existence of the keyErrorNumber parameter of the reply Apple event to ensure that the server performed the requested action. The server can also return, in the keyErrorString parameter, any error messages you need to display to the user.
  4335. Whenever a server application provides an error string, it should also provide an error number. However, you can’t count on all server applications to do so. The absence of the keyErrorNumber parameter doesn’t necessarily mean that there won’t an error string provided in the keyErrorString parameter. A client application should therefore check for both the keyErrorNumber and keyErrorString parameters before assuming that no error has occurred. If a string has been provided without an error number, an error has occurred. 
  4336. After extracting the information it needs from the reply event, your handler should dispose of the reply by calling the AEDisposeDesc function. Similarly, when your handler no longer needs descriptor records it has extracted from the reply, it should call AEDisposeDesc to dispose of them.
  4337. The next section provides an overview of the way a source application identifies Apple event objects supported by a target application. If you are starting by supporting only the Required suite and the Apple events sent by the Edition Manager, you can skip the next section and go directly to “About the Apple Event Manager,” which begins on page 3-48. 
  4338.  
  4339. Working With Object Specifier Records
  4340.  
  4341. Most of the standard Apple events allow the source application to refer, in an Apple event parameter, to Apple event objects within the target application or its documents. The Apple Event Manager allows applications to construct and interpret such references by means of a standard classification system for Apple event objects. This system, described in detail in the Apple Event Registry: Standard Suites, is summarized in “The Classification of Apple Event Objects,” which begins on page 3-39. A description in an Apple event parameter that uses this classification system takes the form of an object specifier record.
  4342. An object specifier record is a descriptor record of descriptor type typeObjectSpecifier that describes the location of one or more Apple event objects: for example, the table “Summary of Sales” in the document “Sales Report,” or the third row in that table, or the last row of the column “Totals.” With the aid of application-defined functions, the Apple Event Manager can conduct a step-by-step search according to such instructions in an object specifier record, locating first the document, then the table, then other objects, and so on until the requested object has been identified. Object specifier records can specify many combinations of identifying characteristics that cannot be specified using one of the simple data types. 
  4343. This section introduces object specifier records and the organization of their data. You need to read this section (a) if you plan to support the Core suite or any of the standard functional-area suites and (b) if you want to make your application scriptable—that is, capable of responding to scripts written in a scripting language.
  4344. IMPORTANT
  4345. An object specifier record identifies one or more Apple event objects among many; it contains a description of each object, not the object itself. An Apple event object described by an object specifier record exists only in the server application’s document or in the server application itself.s
  4346. A client application cannot retrieve an Apple event object from a server application unless the server application can accurately locate it. Thus, to locate characters of a specific color, a server application must be able to identify a single character’s color; to locate a character in a cell, a server application must be able to locate both the table and the cell.
  4347. A client application can create object specifier records for use as Apple event parameters. Scripting components can also create object specifier records as Apple event parameters for the Apple events they generate in the course of executing a script. A server application that receives an Apple event containing an object specifier record should resolve the object specifier record—that is, locate the requested Apple event objects. 
  4348. To respond to core and functional-area Apple events received by your application, you must first define a hierarchy of Apple event objects for your application that you want other applications or scripting languages to be able to describe. The Apple event objects for your application should be based as closely as possible on the standard object classes described by the Apple Event Registry: Standard Suites. After you have decided which of the standard Apple event objects make sense for your application, you can write functions that locate objects on the basis of information in an object specifier record. If you want your application to send specific Apple events to other applications, you must also write functions that can create object specifier records and add them to Apple events. Your application does not need to create object specifier records in order to be scriptable. However, to write functions that can help the Apple Event Manager resolve object specifier records, you need to know how they are constructed. 
  4349. “Finding Apple Event Objects,” which begins on page 3-46, provides an overview of the way the Apple Event Manager works with your application-defined functions to locate the Apple event objects described in an object specifier record. The chapter “Resolving and Creating Object Specifier Records” in this book describes in detail how to support object specifier records as a server or client application. 
  4350. Data Structures Within an Object Specifier Record
  4351.  
  4352. The organization of the data for an object specifier record is nearly identical to that of the data for an AE record. An object specifier record is a structure of data type AEDesc whose data handle usually refers to four keyword-specified descriptor records describing one or more Apple event objects. An AE record is a structure of data type AERecord whose data handle refers to one or more Apple event parameters.
  4353. The four keyword-specified descriptor records for an object specifier record provide information about the requested Apple event object or objects.
  4354. Keyword    Description of data    
  4355. keyAEDesiredClass    Four-character code indicating the object class ID    
  4356. keyAEContainer    A description of the container for the requested object, usually in the form of another object specifier record    
  4357. keyAEKeyForm    Four-character code for the key form, which indicates how to interpret the key data    
  4358. keyAEKeyData    Key data, used to distinguish the desired Apple event object from other objects of the same object class in the same container    
  4359.  
  4360. For example, the data for an object specifier record identifying a table named “Summary of Sales” in a document named “Sales Report” consists of four keyword-specified descriptor records that provide the following information:
  4361. n    the object class ID for a table
  4362. n    another object specifier record identifying the document “Sales Report” as the container for the table
  4363. n    a key form constant indicating that the key data contains a name
  4364. n    key data that consists of the string “Summary of Sales”
  4365. The object class ID specifies the Apple event object class to which the object belongs. An Apple event object class is a category for Apple event objects that share specific characteristics (see “Apple Events and Apple Event Objects” on page 3-6). The characteristics of each object class are listed in the Apple Event Registry: Standard Suites. For example, the Core suite defines object classes for documents, paragraphs, words, windows, and floating windows. The first keyword-specified descriptor record in an object specifier record uses a four-character code or a constant to specify the object class ID. The object class for words, for example, can be identified by either the object class ID 'cwor' or the constant cWord. 
  4366. Note
  4367. The object class ID identifies the object class of an Apple event object described in an object specifier record, whereas the event class and event ID identify an Apple event.u
  4368. The container for an Apple event object is usually another Apple event object. For example, the container for a document might be a window, and the container for characters, delimited items, or a word might be another word, a paragraph, or a document. The container is identified by the second keyword-specified descriptor record in an object specifier record; usually this is another object specifier record. The container can also be specified by a null descriptor record, which indicates a default container or a container already known to the Apple Event Manager.
  4369. The descriptor record in an object specifier record that identifies an Apple event object’s container can in turn use another object specifier record to identify the container’s container, and so on until the Apple event object is fully specified. For example, an object specifier record identifying a paragraph might specify the paragraph’s container with another object specifier record that identifies a page. That object specifier record might in turn specify the page’s container with another object specifier record identifying a document. The ability to nest one object specifier record within another in this way makes it possible to identify elements such as “the first row in the table named ‘Summary of Sales’ in the document named ‘Sales Report.’” 
  4370. The key form and key data distinguish the desired Apple event object from other Apple event objects of the same object class. The key form describes the form the key data takes. The third keyword-specified descriptor record in an object specifier record usually specifies the key form with one of seven standard constants:
  4371. Key form    Value    Corresponding key data    
  4372. formPropertyID    'prop'    Property ID for an element’s property    
  4373. formName    'name'    Element’s name    
  4374. formUniqueID    'ID  '    A value that uniquely identifies an object within its container or across an application    
  4375. formAbsolutePosition    'indx'    An integer or other constant indicating the position of one or more elements in relation to the beginning or end of their container    
  4376. formRelativePosition    'rele'    A constant that specifies the element just before or after the container    
  4377. formTest    'test'    Descriptor records that specify a test    
  4378. formRange    'rang'    Descriptor records that specify a group of elements between two other elements     
  4379.  
  4380. A key form of formPropertyID indicates key data that specifies a property. A property of an Apple event object is a specific characteristic of that object that can be identified by a constant. The properties associated with the object class for documents include the name of the document and a flag indicating whether the document has been modified since the last save. The properties associated with the object class for words include color, font, point size, and style.
  4381. Figure 3-13 shows the structure of a typical object specifier record: four keyword-specified descriptor records that specify the class ID, the container, the key form, and the key data. These four keyword-specified descriptor records are the data for a descriptor record (AEDesc) of descriptor type typeObjectSpecifier. Note the similarities between the object specifier record shown in Figure 3-13 and the Apple event record shown in Figure 3-9 on page 3-19. Like an Apple event record or an AE record, an object specifier record consists of a list of keyword-specified descriptor records. 
  4382. Figure 3-13 shows the structure of a simple object specifier record that specifies the key form formPropertyID, formName, or formAbsolutePosition. For detailed information about the structure of object specifier records that specify the other key forms, see the chapter “Resolving and Creating Object Specifier Records” in this book. 
  4383. Figure 3-13    Data structures within a simple object specifier record
  4384.  
  4385. Figure 3-14 shows the object specifier record for the Get Data event previously illustrated in Figure 3-4 on page 3-11. The object class ID tells the SurfWriter application that the requested data is an element of class cTable. The container for the table is the document “Sales Report.” The key form is formName, which tells the server application that the key data identifies the Apple event object by name. The key data is the name of the table.
  4386. Figure 3-14    An object specifier record in a Get Data event
  4387.  
  4388. To add an object specifier record to an Apple event as one of its parameters, your application must first create the object specifier record. “Creating Object Specifier Records,” which begins on page 6-55, describes the Apple Event Manager routines for creating object specifier records.
  4389. To respond to Apple events that include object specifier records, your application should use the standard classification system for Apple event objects and provide functions that can locate those objects within your application or its documents. The next section summarizes the classification of Apple event objects as defined in the Apple Event Registry: Standard Suites. 
  4390. The Classification of Apple Event Objects
  4391.  
  4392. To create or resolve object specifier records, your application should use the classification of Apple event objects defined by the Apple Event Registry: Standard Suites. This section summarizes the concepts that underlie that classification system. You should have a copy of the Apple Event Registry: Standard Suites available for reference purposes while you read this section.
  4393. You do not need to write your application in an object-oriented programming language in order to support Apple event objects in your application. However, you must understand the classification system described in this section in order to classify Apple event objects in your application and to write routines that can locate them on the basis of information contained in object specifier records.
  4394. Object Classes
  4395.  
  4396. Except for the concept of inheritance, Apple event objects are different from the objects used in object-oriented programming languages. Apple event objects are distinct items in a server application or any of its documents that can be specified by an object specifier record in an Apple event sent by a client application. Apple event objects are often, but not always, items that a user can differentiate and manipulate within an application, such as words, paragraphs, shapes, windows, or style formats. Every Apple event object can be classified according to its object class, which defines both its characteristics and its behavior. The object classes listed in the Apple Event Registry: Standard Suites provide a method of describing Apple event objects that all applications can understand. Object classes permit more flexibility than simple descriptor types; for example, a word can be defined as a simple string, or it can be defined as an Apple event object with specific characteristics such as font or style.
  4397. Note
  4398. The definition of an object class only specifies conventions that determine how applications should handle Apple event objects that belong to that class. Your application must make sure that it uses the conventions correctly; they are not enforced by the Apple Event Manager.u
  4399. Each object class is identified by a four-character object class ID, which can also be represented by a constant. Constants for object classes always begin with the letter c. 
  4400. The definition of an object class specifies its superclass, which is the object class from which a subclass (the class being defined) inherits some of its characteristics. Characteristics can also be inherited from special object classes, called abstract superclasses, that are used only in definitions of object classes and do not refer to real Apple event objects. The pattern of inheritance among object classes is called the object class inheritance hierarchy. Figure 3-15 shows a portion of this hierarchy. The abstract superclass cObject is at the top of the hierarchy and is therefore the only object class that has no superclass. At the next level are cText, which is a regular object class, and cOpenableObject, which is an abstract superclass. Both are subclasses of cObject and superclasses for their own subclasses. The object classes cWord, cItem, and cChar are all subclasses of cText. Similarly, cWindow, cDocument, and cFile are subclasses of cOpenableObject. Every object class inherits all the characteristics of its superclass and can also add characteristics of its own.
  4401. Figure 3-15    Superclasses and subclasses
  4402.  
  4403. Here are some of the object classes defined for the Core suite:
  4404. Class    Class ID    Description    
  4405. cChar    'cha '    Text characters    
  4406. cDocument    'docu'    Macintosh documents    
  4407. cFile    'cfil'    Macintosh files    
  4408. cSelection    'csel'    User or application selections    
  4409. cText    'ctxt'    Series of characters    
  4410. cWindow    'cwin'    Standard Macintosh windows    
  4411.  
  4412. Here are some of the object classes defined for the Text suite:
  4413. Class    Class ID    Description    
  4414. cChar    'cha '    Text characters    
  4415. cLine    'clin'    Lines of text    
  4416. cParagraph    'cpar'    Paragraphs    
  4417. cText    'ctxt'    Series of characters    
  4418. cTextFlow    'cflo'    Text flows    
  4419. cWord    'cwor'    Words    
  4420.  
  4421. As you can see, some object classes, such as cChar and cText, are defined in more than one suite. For example, the definition of the cText object class in the Text suite is an extension of the cText object class defined in the Core suite; it duplicates all the characteristics of the Core suite object class and adds some of its own. Like a word in a dictionary, one object class ID can have several related definitions. You can choose to support the definition that best suits your application; or, if necessary, you can create extensions of your own. The extension of an object class is different from inheritance between object classes. An extension of a standard object class provides additional ways of describing an Apple event object of that class, whereas the object class inheritance hierarchy determines the pattern of characteristics shared by different object classes. 
  4422. The definition of an object class always specifies a default descriptor type. Suppose, for example, that a client application sends a Get Data, Cut, or Copy event that specifies an Apple event object but does not specify a descriptor type for the returned data. In this case, the server application returns a descriptor record of the default descriptor type for the object class of the specified Apple event object. For example, the default descriptor type for Apple event objects of class cWord is typeIntlText, a descriptor type that specifies an undelimited string of characters in a specific language and script system. The client application can also request that the data be returned in a descriptor record of some other data type.
  4423. The definition of an object class includes three lists of characteristics: properties, element classes, and Apple events that support the object class. (The next section describes properties and element classes.) Any or all of these characteristics may be inherited from a superclass. An Apple event is listed for an object class if its parameters can specify objects of that class. The definition for cWindow, for example, lists 12 Apple events, including the Open, Close, and Move events, whose parameters can include object specifier records that specify windows. The cWindow class inherits all of these Apple events from its abstract superclass, cOpenableObject.
  4424. The Apple Event Registry: Standard Suites also defines primitive object classes, which describe Apple event objects that contain a single value. For example, the cBoolean, cLongInteger, and cAlias object classes are all primitive object classes. The object class ID for a primitive object class is the same as the four-character value of its descriptor type. Primitive object classes contain no properties; they contain only the value of the data.  
  4425. Properties and Elements
  4426.  
  4427. The properties listed for an object class can be used to identify characteristics of Apple event objects that belong to that class. Each property is identified by a four-character property ID, which can also be represented by a constant. Constants for properties always begin with the letter p.
  4428. Here are constants and property IDs for some properties:
  4429. Property    Property ID    Description    
  4430. pName    'pnam'    Name of an Apple event object    
  4431. pBounds    'pbnd'    Coordinates of a window    
  4432. pVisible    'pvis'    Indicates whether a window is visible    
  4433. pIsModal    'pmod'    Indicates whether a window is modal    
  4434. pClass    'pcls'    Class ID of an Apple event object    
  4435. pFont    'font'    Font    
  4436. pTextStyle    'txst'    Text style    
  4437. pColor    'colr'    Text color    
  4438. pTextPointSize    'ptps'    Point size    
  4439. pScriptTag    'psct'    Script system identifier    
  4440. pFillColor    'flcl'    Fill color    
  4441.  
  4442. The property of an Apple event object is itself defined as a single Apple event object whose container is the object to which the property belongs. For example, the pFont property of a word is defined by the name of a font, such as New York; the string that identifies the font is an Apple event object of class cText. 
  4443. The constant cProperty specifies the object class for any object specifier record that identifies a property. 
  4444. CONST cProperty = 'prop';
  4445. An object specifier record for a property specifies cProperty as the object class ID, the Apple event object to which the property belongs as the container, formPropertyID as the key form, and a constant such as pFont as the key data.   
  4446. The elements of a specific Apple event object are the other Apple event objects it contains, excluding those that define its properties. An object specifier record for an element specifies the Apple event object in which the element is located as the container and can specify any key form except formPropertyID. Each object class definition in the Apple Event Registry: Standard Suites includes a list of element classes, which are the object classes of the elements that an Apple event object can contain. 
  4447. An Apple event object contains exactly one of each of its properties, whereas it can contain no elements or many elements of the same element class. In general, a property of an object describes something about that object; a property can be examined or changed but never deleted. An element can be one or more discrete objects contained in another object and can usually be deleted. 
  4448. For example, because a paragraph can contain one or more words, one of the element classes listed for the object class cParagraph is the object class cWord. Individual words can be deleted from a paragraph. However, even though a word in a paragraph can be in a different font from the words around it, a paragraph can have only one pFont property. This property is defined as the font of the first character in the paragraph and consists of the name of a font. The paragraph’s pFont property can be changed but not removed.
  4449. The properties and element classes listed for each object class definition in the Apple Event Registry: Standard Suites can be inherited from a superclass, or they can originate with a subclass. Figure 3-16 illustrates the object class inheritance hierarchy for the object class cWindow in the Core suite. Boldface terms in the figure represent those properties, element classes, or Apple events that are not inherited. The object class cWindow includes all the properties and Apple events of its superclass, cOpenableObject, which in turn includes all the properties and Apple events of its superclass, cObject. The object class cWindow also includes 11 properties and one element class that originate with cWindow and are not inherited. 
  4450. The pClass property—the property that specifies the four-character class ID—originates with cObject. Because the definitions of all object classes are ultimately derived from cObject, pClass is inherited by all object classes. The definition for cObject also lists ten Apple events, which include common events such as Get Data, Move, and Delete Element. Because cObject is at the top of the object class inheritance hierarchy, these ten Apple events can use object specifier records that describe Apple event objects of any object class as a direct parameter. Like all abstract superclasses, cObject does not correspond to a real Apple event object, so its definition does not list any element classes. Unlike any other object class, cObject is at the top of the object class inheritance hierarchy and therefore does not have a superclass. 
  4451. Figure 3-16    The object class inheritance hierarchy for the object class cWindow
  4452.  
  4453. The chain of containers that determine the location of one or more Apple event objects is called the container hierarchy. The container hierarchy, which specifies the location of real Apple event objects, is different from the object class inheritance hierarchy, which is an abstract concept that determines which properties, element classes, and Apple events an object class inherits from its superclass. For example, the container hierarchy for an Apple event object of class cWord can vary from one word to another, because various combinations of other Apple event objects, such as a document, a paragraph, a delimited string, or another word, can contain a word. 
  4454. Applications that support Apple event objects must be able to identify the order of several elements of the same class that are contained within another Apple event object. For example, each word in a paragraph should have an identifiable order, such as the 5th word or the 12th word. This allows other applications to identify Apple event objects by describing their absolute position within a container. 
  4455. Figure 3-17 shows an Apple event object of object class cWord—the word “Sales”—contained in another Apple event object of object class cParagraph. (Both these object classes are defined in the Text suite.) The figure shows only a portion of the container hierarchy for the word, since a complete description of the word would also include the containers that specify the location of the paragraph. 
  4456. Your application must take account of the definitions in the Apple Event Registry: Standard Suites for any object classes you want to support. For example, the definition for the object class cText lists paragraphs, lines, words, and characters as Apple event objects that can be contained in Apple event objects of class cText. To support Apple events that refer to elements of object class cText, your application should associate the cText object class with paragraphs, lines, words, and characters in its documents. The list of properties defined for class cText includes the properties pColor, pFont, pPointSize, pScriptTag, and pTextStyles. If you want to support Apple events that distinguish a boldface 12-point word of object class cText from an italic 14-point word, for example, your application must associate the point size and style of text in its documents with the properties pPointSize and pTextStyles defined for class cText. 
  4457. Figure 3-17    An Apple event object of class cWord contained in an Apple event object of class cParagraph
  4458.  
  4459. Finding Apple Event Objects
  4460.  
  4461. Most of the Apple events in the Core suite and the functional-area suites defined in the Apple Event Registry: Standard Suites can include parameters that consist of object specifier records. Your application’s handlers for these events can use the AEResolve function to resolve object specifier records: that is, to locate the Apple event objects they describe.
  4462. The AEResolve function parses an object specifier record and performs related tasks that are the same for all object specifier records. When necessary, the AEResolve function calls application-defined functions to perform tasks that are unique to the application, such as locating a specific Apple event object in the application’s data structures.
  4463. Your application can provide two kinds of application-defined functions for use by AEResolve. Object accessor functions locate Apple event objects. Every application that supports simple object specifier records must provide one or more object accessor functions. Object callback functions perform other tasks that only an application can perform, such as counting, comparing, or marking Apple event objects. 
  4464. Each time AEResolve calls one of your application’s object accessor functions successfully, the object accessor function returns a special descriptor record, called a token, that identifies either an element in a specified container or a property of a specified Apple event object. The token can be of any descriptor type, including descriptor types you define yourself. 
  4465. You install object accessor functions by using the AEInstallObjectAccessor function. Much like the AEInstallEventHandler function, AEInstallObjectAccessor uses an object accessor dispatch table to map requests for Apple event objects to the appropriate object accessor functions in your application. These requests refer to objects of a specified object class in containers identified by a token of a specified descriptor type.
  4466. Responding to an Apple event that includes an object specifier record typically involves these steps:
  4467.     1.    After determining that the event is an Apple event, your application calls AEProcessAppleEvent.
  4468.     2.    The AEProcessAppleEvent function uses the Apple event dispatch table to dispatch the event to the your application’s handler for that event.
  4469.     3.    The Apple event handler extracts the Apple event parameters, and passes the object specifier records they contain to AEResolve.
  4470.     4.    The AEResolve function uses the object accessor dispatch table to call one or more object accessor functions, one at a time, that can identify the nested Apple event objects described by each object specifier record. Each object accessor function returns a token for the object it finds, which in turn helps to determine which object accessor function the AEResolve function will use to locate the next Apple event object.
  4471.     5.    The AEResolve function returns the final token for the requested object to the application’s handler.
  4472. The resolution of an object specifier record always begins with the outermost container it specifies. For example, to locate a table named “Summary of Sales” in the document named “Sales Report,” the AEResolve function first calls an object accessor function that can locate the document, then uses the token returned by that function to identify an object accessor function that can locate the table. It then returns the token for the table to the Apple event handler that called AEResolve.
  4473. The chapter “Resolving and Creating Object Specifier Records” in this book describes in detail how to resolve object specifier records and how to write and install object accessor and object callback functions. 
  4474.  
  4475.  
  4476. About the Apple Event Manager
  4477.  
  4478. You can use the Apple Event Manager to
  4479. n    respond to Apple events as a server application
  4480. n    create and send Apple events as a client application
  4481. n    resolve and create object specifier records
  4482. n    support Apple event recording
  4483. This section briefly summarizes the steps involved in providing each kind of support and tells where to find the relevant information in this book.
  4484. Supporting Apple Events as a Server Application
  4485.  
  4486. You do not need to implement all Apple events at once. You can begin by supporting just the required events and, if necessary, the events sent by the Edition Manager. The beginning of the section “Handling Apple Events” on page 4-4 describes how to provide this minimal level of support.
  4487. It is relatively easy to respond to the required events and the events sent by the Edition Manager. If, however, your application cannot respond to any other Apple events, other applications will not be able to request services that involve locating specific Apple event objects within your application or its documents, and users will not be able to control your application by executing scripts. To respond to Apple events it is likely to receive from other applications or from scripting components, your application must be able to respond to the appropriate core and functional-area Apple events. 
  4488. Once you have provided the basic level of support for the Required suite and for events sent by the Edition Manager, you should
  4489. n    decide which other Apple event suites you want to support
  4490. n    define the hierarchy of Apple event objects within your application that you want scripting components or other applications to be able to identify—that is, which Apple event objects can be contained by other Apple event objects in your application
  4491. n    write handlers for the Apple events you support, and install corresponding entries in your application’s Apple event dispatch table
  4492. To decide which Apple event suites you want to support and how to define the hierarchy of Apple event objects in your application, consult the Apple Event Registry: Standard Suites and evaluate which Apple events and Apple event object classes make sense for your application. If necessary, you can extend the definitions of the standard Apple events and Apple events objects to cover special requirements of your application. It is better to extend the standard definitions rather than to define your own custom Apple events, because only those applications that choose to support your custom Apple events explicitly will be able to make use of them.
  4493. The chapter “Responding to Apple Events” in this book describes how to write Apple event handlers and related routines. The chapter “Resolving and Creating Object Specifier Records” describes how to resolve object specifiers in an Apple event that describes Apple event objects in your application or its documents.
  4494. If your application can respond to Apple events, you can make it scriptable simply by adding an 'aete' resource. Scripting components use your application’s 'aete' resource to obtain information about the Apple events and corresponding human-language terminology that your application supports. The chapter “Apple Event Terminology Resources” in this book describes how to optimize your implementation of Apple events for use by scripting components and how to create an 'aete' resource.
  4495. Supporting Apple Events as a Client Application
  4496.  
  4497. Because users can send Apple events to a variety of applications simply by executing a script, many applications have no need to send Apple events. However, if you want to factor your application for recording, or if you want your application to send Apple events directly to other applications, you can use Apple Event Manager routines to create and send Apple events. 
  4498. To send an Apple event, you must
  4499. n    create the Apple event
  4500. n    add parameters and attributes
  4501. n    use the AESend function to send the event
  4502. The chapter “Creating and Sending Apple Events” in this book describes how to perform these tasks.
  4503. Supporting Apple Event Objects
  4504.  
  4505. If your application responds to core and functional-area Apple events, it must also be able to resolve object specifier records that describe the objects on which those Apple events can act. In addition to the tasks described in the chapter “Responding to Apple Events,” you must perform the following tasks to handle Apple events that contain object specifier records:
  4506. n    Write object accessor functions that can locate the Apple event objects you support, and install corresponding entries in your application’s object accessor dispatch table.
  4507. n    Write any object callback functions that you decide to provide. To handle object specifier records that specify a test, your application must provide at least two object callback functions: one that counts objects and one that compares them.
  4508. n    Call AEResolve from your Apple event handlers whenever an Apple event parameter includes an object specifier record. 
  4509. The chapter “Resolving and Creating Object Specifier Records” describes how to perform these tasks. It also describes how applications that send Apple events to themselves or directly to other applications can create object specifier records.
  4510. Supporting Apple Event Recording
  4511.  
  4512. If you make your application scriptable, you may also want to make it recordable. Users of recordable applications can record their actions in the form of Apple events that a scripting component translates into a script. When a user executes a recorded script, the scripting component sends the same Apple events to the application in which they were recorded.
  4513. To make your application recordable, you should use Apple events to report user actions to the Apple Event Manager in terms of Apple events. One way to do this is to separate the code that implements your application’s user interface from the code that actually performs work when the user manipulates the interface. This is called factoring your application. A factored application acts as both the client and server application for Apple events it sends to itself in response to user actions. When recording is turned on, the Apple Event Manager sends a copy of every event than an application sends to itself to the scripting component or other process that turned recording on.
  4514. The chapter “Introduction to Scripting” in this book provides an overview of how to make your application both scriptable and recordable. The chapter “Recording Apple Events” describes how to factor your application for recording and explains the Apple Event Manager’s recording mechanism.
  4515. Listing 4-0
  4516. Table 4-0
  4517. Responding to Apple Events
  4518. Contents
  4519. Handling Apple Events4-4
  4520. Accepting an Apple Event4-5
  4521. Installing Entries in the Apple Event Dispatch Tables4-7
  4522. Installing Entries for the Required Apple Events4-8
  4523. Installing Entries for Apple Events Sent by the Edition Manager4-9
  4524. How Apple Event Dispatching Works4-9
  4525. Handling the Required Apple Events4-11
  4526. Required Apple Events4-11
  4527. Handling the Open Application Event4-14
  4528. Handling the Open Documents Event4-15
  4529. Handling the Print Documents Event4-17
  4530. Handling the Quit Application Event4-19
  4531. Handling Apple Events Sent by the Edition Manager4-20
  4532. The Section Read, Section Write, and Section Scroll Events4-21
  4533. Handling the Create Publisher Event4-22
  4534. Getting Data Out of an Apple Event4-25
  4535. Getting Data Out of an Apple Event Parameter4-26
  4536. Getting Data Out of an Attribute4-28
  4537. Getting Data Out of a Descriptor List4-31
  4538. Writing Apple Event Handlers4-33
  4539. Replying to an Apple Event4-36
  4540. Disposing of Apple Event Data Structures4-39
  4541. Writing and Installing Coercion Handlers4-41
  4542. Interacting With the User4-45
  4543. Setting the Client Application’s User Interaction Preferences4-46
  4544. Setting the Server Application’s User Interaction Preferences4-48
  4545. Requesting User Interaction4-49
  4546. Reference to Responding to Apple Events4-56
  4547. Data Structures Used by the Apple Event Manager4-56
  4548. Descriptor Records and Related Data Structures4-56
  4549. Apple Event Array Data Types4-60
  4550. Routines for Responding to Apple Events4-61
  4551. Creating and Managing the Apple Event Dispatch Tables4-61
  4552. Dispatching Apple Events4-66
  4553. Getting Data or Descriptor Records Out of Apple Event Parameters and Attributes4-68
  4554. Counting the Items in Descriptor Lists4-74
  4555. Getting Items From Descriptor Lists4-74
  4556. Getting Data and Keyword-Specified Descriptor Records Out of AE Records4-78
  4557. Requesting User Interaction4-81
  4558. Requesting More Time to Respond to Apple Events4-84
  4559. Suspending and Resuming Apple Event Handling4-85
  4560. Getting the Sizes and Descriptor Types of Descriptor Records4-89
  4561. Deleting Descriptor Records4-92
  4562. Deallocating Memory for Descriptor Records4-93
  4563. Coercing Descriptor Types4-94
  4564. Creating and Managing the Coercion Handler Dispatch Tables4-96
  4565. Creating and Managing the Special Handler Dispatch Tables4-99
  4566. Getting Information About the Apple Event Manager4-103
  4567. Application-Defined Routines4-104
  4568. Summary of Responding to Apple Events4-108
  4569. Pascal Summary4-108
  4570. Constants4-108
  4571. Data Types4-112
  4572. Routines for Responding to Apple Events4-114
  4573. Application-Defined Routines4-118
  4574. C Summary4-118
  4575. Constants4-118
  4576. Data Types4-123
  4577. Routines for Responding to Apple Events4-124
  4578. Application-Defined Routines4-128
  4579. Assembly-Language Summary4-128
  4580. Trap Macros4-128
  4581. Result Codes4-130
  4582. Responding to Apple Events
  4583. This chapter describes how your application can use the Apple Event Manager to respond to Apple events. Your application must be able to respond to the four required Apple events to take advantage of the launching and terminating mechanisms that are part of System 7 and later versions of system software. If your application provides publish and subscribe capabilities, it should also handle the events sent by the Edition Manager. To be scriptable, or capable of responding to Apple events sent by scripting components, your application should handle the appropriate core and functional-area Apple events.
  4584. Before you read this chapter, you should be familiar with the chapters “Introduction to Interapplication Communication” and “Introduction to Apple Events” in this book. You should also have a copy of the Apple Event Registry: Standard Suites available for reference. 
  4585. Although the Apple events used by the Edition Manager are discussed in this chapter, you must refer to the chapter “Edition Manager” in this book for a full discussion of how to implement the Edition Manager’s publish and subscribe features.
  4586. This chapter provides the basic information you need to make your application capable of responding to Apple events. To respond to core and functional-area Apple events, your application must also be able to resolve object specifier records. You should read the chapter “Resolving and Creating Object Specifier Records” before you write Apple event handlers for events that can contain object specifier records.
  4587. The section “Handling Apple Events,” which begins on page 4-4, describes how to
  4588. n    accept and process Apple events
  4589. n    install entries in the Apple event dispatch tables
  4590. n    handle the required events
  4591. n    handle events sent by the Edition Manager
  4592. n    get data out of an Apple event
  4593. n    write handlers that perform the action requested by an Apple event
  4594. n    reply to an Apple event
  4595. n    dispose of Apple event data structures
  4596. n    write and install coercion handlers
  4597. The section “Interacting With the User,” which begins on page 4-45, describes 
  4598. n    how a server application can interact with the user when processing an Apple event
  4599. n    how client applications set user interaction preferences
  4600. n    how the client application’s preferences and the server application’s preferences affect user interaction
  4601.  
  4602.  
  4603. Handling Apple Events
  4604.  
  4605. You do not need to implement all Apple events at once. If you want to begin by supporting only the required Apple events, you must
  4606. n    set bits in the 'SIZE' resource to indicate that your application supports high-level events
  4607. n    include code to handle high-level events in your main event loop
  4608. n    write routines that handle the required events
  4609. n    install entries for the required Apple events in your application’s Apple event dispatch table 
  4610. The following sections explain how to perform these tasks: “Accepting an Apple Event,” which begins on page 4-5, “Installing Entries in the Apple Event Dispatch Tables,” which begins on page 4-7, and “Handling the Required Apple Events,” which begins on page 4-11.
  4611. To respond to the Apple events sent by the Edition Manager in addition to the required events, you must install entries for the Section Read, Section Write, Section Scroll, and Create Publisher events in your application’s Apple event dispatch table and write the corresponding handlers, as described in “Handling Apple Events Sent by the Edition Manager” on page 4-20. 
  4612. To respond to core and functional-area Apple events, you must install entries and write handlers for those events. You must also make sure that your application can locate Apple event objects with the aid of the Apple Event Manager routines described in the chapter “Resolving and Creating Object Specifier Records.” These routines are currently available as the Object Support Library (OSL), which you must link with your application when you build it. 
  4613. The Apple Event Manager (excluding the OSL) is available only in System 7 and later versions of system software. Use the Gestalt function with the gestaltAppleEventsAttr selector to determine whether the Apple Event Manager is available. In the response parameter, the bit defined by the constant gestaltAppleEventsPresent is set if the Apple Event Manager is available.
  4614. CONST        gestaltAppleEventsAttr  = 'evnt';                                                {Gestalt selector}
  4615.         gestaltAppleEventsPresent = 0;                                                {if this bit is set, } 
  4616.                                                         { then the Apple Event }
  4617.                                                         { Manager is available}
  4618. To find out which version of the Apple Event Manager is available, you can use the AEManagerInfo function; for more information, see page 4-104.
  4619. Accepting an Apple Event
  4620.  
  4621. To accept or send Apple events (or any other high-level events), you must set the appropriate flags in your application’s 'SIZE' resource and include code to handle high-level events in your application’s main event loop. 
  4622. Two flags in the 'SIZE' resource determine whether an application receives high-level events: 
  4623. n    The isHighLevelEventAware flag must be set for your application to receive any high-level events.
  4624. n    The localAndRemoteHLEvents flag must be set for your application to receive high-level events sent from another computer on the network.
  4625. Note that in order for your application to respond to Apple events sent from remote computers, the user of your application must also allow network users to link to your application. The user does this by selecting your application in the Finder, choosing Sharing from the File menu, and clicking the Allow Remote Program Linking checkbox. If the user has not yet started program linking, the Sharing command offers to display the Sharing Setup control panel so that the user can start program linking. The user must also authorize remote users for program linking by using the Users & Groups control panel. Program linking and setting up authenticated sessions are described in the chapter “Program-to-Program Communications Toolbox” in this book.
  4626. For a complete description of the 'SIZE' resource, see the chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials. 
  4627. Apple events (and other high-level events) are identified by a message class of kHighLevelEvent in the what field of the event record. You can test the what field of the event record to determine whether the event is a high-level event.
  4628. Listing 4-1 is an example of a procedure called from an application’s main event loop to handle events, including high-level events. The procedure determines the type of event received and then calls another routine to take the appropriate action.
  4629. Listing 4-1    A DoEvent procedure
  4630.  
  4631. PROCEDURE DoEvent (event: EventRecord);
  4632. BEGIN                
  4633.     CASE event.what OF                                    {determine the type of event}
  4634.         mouseDown:
  4635.             DoMouseDown (event);
  4636.         .
  4637.         . {handle other kinds of events}
  4638.         .
  4639.         {handle high-level events, including Apple events}
  4640.         kHighLevelEvent: DoHighLevelEvent (event);
  4641.     END;
  4642. END; 
  4643. Listing 4-2 is an example of a procedure that handles both Apple events and the high-level event identified by the event class mySpecialHLEventClass and the event ID mySpecialHLEventID. Note that, in most cases, you should use Apple events to communicate with other applications. 
  4644. Listing 4-2    A DoHighLevelEvent procedure for handling Apple events and other high-level events
  4645. PROCEDURE DoHighLevelEvent (event: EventRecord);
  4646. VAR
  4647.     myErr: OSErr;
  4648. BEGIN
  4649.     IF (event.message = LongInt(mySpecialHLEventClass)) AND
  4650.         (LongInt(event.where) = LongInt(mySpecialHLEventID)) 
  4651.     THEN
  4652.         {it's a high-level event that doesn't use AEIMP}
  4653.         myErr := HandleMySpecialHLEvent(event)
  4654.     ELSE
  4655.         {otherwise, assume that the event is an Apple event}
  4656.         myErr := AEProcessAppleEvent(event);
  4657.     
  4658.     {check and handle error}
  4659.     IF myErr <> noErr THEN DoError(myErr);
  4660. END;
  4661. If your application accepts high-level events that do not follow the Apple Event Interprocess Messaging Protocol (AEIMP), you must dispatch these high-level events before calling AEProcessAppleEvent. To dispatch high-level events that do not follow AEIMP, you should check the event class, the event ID, or both for each event to see whether your application can handle the event. 
  4662. After receiving a high-level event (and, if appropriate, checking whether it is a high-level event other than an Apple event), your application typically calls the AEProcessAppleEvent function. The AEProcessAppleEvent function determines the type of Apple event received, gets the event buffer that contains the parameters and attributes of the Apple event, and calls the corresponding Apple event handler in your application.
  4663. You should provide an Apple event handler for each Apple event that your application supports. This handler is responsible for performing the action requested by the Apple event and if necessary can return data in the reply Apple event. 
  4664. If the client application requests a reply, the Apple Event Manager passes a default reply Apple event to your handler. If the client application does not request a reply, the Apple Event Manager passes a null descriptor record (a descriptor record of descriptor type typeNull and a data handle whose value is NIL) to your handler instead of a default reply Apple event.
  4665. After your handler finishes processing the Apple event and adds any parameters to the reply Apple event, it must return a result code to AEProcessAppleEvent. If the client application is waiting for a reply, the Apple Event Manager returns the reply Apple event to the client.
  4666. Installing Entries in the Apple Event Dispatch Tables
  4667.  
  4668. When your application receives an Apple event, use the AEProcessAppleEvent function to retrieve the data buffer of the event and to route the Apple event to the appropriate Apple event handler in your application. Your application supplies an Apple event dispatch table to map the Apple events your application supports to the Apple event handlers provided by your application.
  4669. To install entries in your application’s Apple event dispatch table, use the AEInstallEventHandler function. You usually install entries for all of the Apple events that your application accepts into your application’s Apple event dispatch table. 
  4670. To install an Apple event handler in your Apple event dispatch table, you must specify
  4671. n    the event class of the Apple event
  4672. n    the event ID of the Apple event
  4673. n    the address of the Apple event handler for the Apple event
  4674. n    a reference constant
  4675. You provide this information to the AEInstallEventHandler function. In addition, you indicate whether the entry should be added to your application’s Apple event dispatch table or to the system Apple event dispatch table. 
  4676. The system Apple event dispatch table is a table in the system heap that contains system Apple event handlers—handlers that are available to all applications and processes running on the same computer. The handlers in your application’s Apple event dispatch table are available only to your application. If AEProcessAppleEvent cannot find a handler for the Apple event in your application’s Apple event dispatch table, it looks in the system Apple event dispatch table for a handler (see 
  4677. “How Apple Event Dispatching Works” on page 4-9 for details). If it doesn’t find a handler for the event, it returns the errAEEventNotHandled result code. 
  4678. If you add a handler to the system Apple event dispatch table, the handler should reside in the system heap. If there was already an entry in the system Apple event dispatch table for the same event class and event ID, it is replaced unless you chain it to your system handler. See “Creating and Managing the Apple Event Dispatch Tables” on page 4-61 for details.
  4679. Installing Entries for the Required Apple Events
  4680.  
  4681. Listing 4-3 illustrates how to add entries for the required Apple events to your application’s Apple event dispatch table.
  4682. Listing 4-3    Adding entries for the required Apple events to an application’s Apple event dispatch table
  4683. myErr := AEInstallEventHandler(kCoreEventClass, 
  4684.                                          kAEOpenApplication, 
  4685.                                          @MyHandleOApp, 0, FALSE);
  4686. IF myErr <> noErr THEN DoError(myErr);
  4687. myErr := AEInstallEventHandler(kCoreEventClass, 
  4688.                                          kAEOpenDocuments, 
  4689.                                          @MyHandleODoc,0, FALSE);
  4690. IF myErr <> noErr THEN DoError(myErr);
  4691. myErr := AEInstallEventHandler(kCoreEventClass, 
  4692.                                          kAEPrintDocuments, 
  4693.                                          @MyHandlePDoc, 0, FALSE);
  4694. IF myErr <> noErr THEN DoError(myErr);
  4695. myErr := AEInstallEventHandler(kCoreEventClass,
  4696.                                          kAEQuitApplication,
  4697.                                          @MyHandleQuit, 0, FALSE); 
  4698. IF myErr <> noErr THEN DoError(myErr);  
  4699. The code in Listing 4-3 creates entries for all four required Apple events in the Apple event dispatch table. (For examples of handlers that correspond to these entries, see “Handling the Required Apple Events,” which begins on page 4-11.) The first entry creates an entry for the Open Application event. The entry indicates the event class and event ID of the Open Application event, supplies the address of the handler for that event, and specifies 0 as the reference constant. 
  4700. The Apple Event Manager passes the reference constant to your handler each time your handler is called. Your application can use this reference constant for any purpose. If your application doesn’t use the reference constant, use 0 as the value. 
  4701. The last parameter to the AEInstallEventHandler function is a Boolean value that determines whether the entry is added to the system Apple event dispatch table or to your application’s Apple event dispatch table. To add the entry to your application’s Apple event dispatch table, use FALSE as the value of this parameter. If you specify TRUE, the entry is added to the system Apple event dispatch table. The code shown in Listing 4-3 adds entries to the application’s Apple event dispatch table.
  4702. Installing Entries for Apple Events Sent by the Edition Manager
  4703.  
  4704. If your application supports the Edition Manager, you should also add entries to your application’s Apple event dispatch table for the Apple events that your application receives from the Edition Manager. Listing 4-4 shows how to add these entries.
  4705. Listing 4-4    Adding entries for Apple events sent by the Edition Manager to an application’s Apple event dispatch table
  4706. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  4707.                                          sectionReadMsgID, 
  4708.                                          @MyHandleSectionReadEvent, 
  4709.                                          0, FALSE);
  4710. IF myErr <> noErr THEN DoError(myErr);
  4711. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  4712.                                          sectionWriteMsgID, 
  4713.                                          @MyHandleSectionWriteEvent, 
  4714.                                          0, FALSE);
  4715. IF myErr <> noErr THEN DoError(myErr);
  4716. myErr := AEInstallEventHandler(sectionEventMsgClass, 
  4717.                                            sectionScrollMsgID, 
  4718.                                          @MyHandleSectionScrollEvent, 
  4719.                                          0, FALSE);
  4720. IF myErr <> noErr THEN DoError(myErr);
  4721. See “Handling Apple Events Sent by the Edition Manager” on page 4-20 for the parameters associated with these events. See the chapter “Edition Manager” in this book for information on how your application should respond to the Apple events sent by the Edition Manager. 
  4722. How Apple Event Dispatching Works
  4723.  
  4724. In addition to the Apple event handler dispatch tables, applications can add entries to a special handler dispatch table in either the application heap or the system heap. These dispatch tables are used for various specialized handlers; for more information, see “Creating and Managing the Special Handler Dispatch Tables,” which begins on page 4-99. 
  4725. When an application calls AEProcessAppleEvent, the function looks first in the application’s special handler dispatch table for an entry that was installed with the constant keyPreDispatch. If the application’s special handler dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the function looks in the application’s Apple event dispatch table for an entry that matches the event class and event ID of the specified Apple event. 
  4726. If the application’s Apple event dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the AEProcessAppleEvent function looks in the system special handler dispatch table for an entry that was installed with the constant keyPreDispatch. If the system special handler dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the function looks in the system Apple event dispatch table for an entry that matches the event class and event ID of the specified Apple event. 
  4727. If the system Apple event dispatch table does not include such a handler, the Apple Event Manager returns the result code errAEEventNotHandled to the server application and, if the client application is waiting for a reply, to the client application.
  4728. sWARNING
  4729. Before an application calls a system Apple event handler, system software has set up the A5 register for the calling application. For this reason, if you provide a system Apple event handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.s
  4730. For any entry in your Apple event dispatch table, you can specify a wildcard value for the event class, event ID, or both. You specify a wildcard by supplying the typeWildCard constant when installing an entry into the Apple event dispatch table. A wildcard value matches all possible values. Wildcards make it possible to supply one Apple event handler that dispatches several related Apple events. 
  4731. For example, if you specify an entry with the typeWildCard event class and the kAEOpenDocuments event ID, the Apple Event Manager dispatches Apple events of any event class with an event ID of kAEOpenDocuments to the handler for that entry. 
  4732. If you specify an entry with the kCoreEventClass event class and the typeWildCard event ID, the Apple Event Manager dispatches Apple events of the kCoreEventClass event class with any event ID to the handler for that entry. 
  4733. If you specify an entry with the typeWildCard event class and the typeWildCard event ID, the Apple Event Manager dispatches all Apple events of any event class and any event ID to the handler for that entry.
  4734. If an Apple event dispatch table contains one entry for an event class and a specific event ID, and also contains another entry that is identical except that it specifies a wildcard value for either the event class or the event ID, the Apple Event Manager dispatches the more specific entry. For example, if an Apple event dispatch table includes one entry that specifies the event class as kAECoreSuite and the event ID as kAEDelete, and another entry that specifies the event class as kAECoreSuite and the event ID as typeWildCard, the Apple Event Manager will dispatch the Apple event handler associated with the entry that specifies the event ID as kAEDelete. 
  4735. IMPORTANT
  4736. IMPORTANT
  4737. If your application sends Apple events to itself using a typeProcessSerialNumber address descriptor record with the lowLongOfPSN field set to kCurrentProcess, the Apple Event Manager jumps directly to the appropriate Apple event handler without going through the normal event-processing sequence. For this reason, your application will not appear to run more slowly when it sends Apple events to itself. For more information, see “Addressing an Apple Event for Direct Dispatching” on page 5-13.s 
  4738. Handling the Required Apple Events
  4739.  
  4740. This section describes the required Apple events—the Apple events your application must support to be compatible with System 7 and later versions of system software—and the descriptor types for all parameters of the required Apple events. It also describes how to write the handlers for these events, and it provides sample code.
  4741. To support the required Apple events, you must set the necessary flags in the 'SIZE' resource of your application, install entries in your application’s Apple event dispatch table, add code to the event loop of your application to recognize high-level events, and call the AEProcessAppleEvent function, as described in “Accepting an Apple Event,” which begins on page 4-5, and “Installing Entries in the Apple Event Dispatch Tables,” which begins on page 4-7. You must also write handlers for each Apple event; this section describes how to write these handlers.
  4742. Required Apple Events
  4743.  
  4744. When a user opens or prints a file from the Finder, the Finder sets up the information your application uses to determine which files to open or print. In System 7 and later versions, if your application supports high-level events, the Finder communicates this information to your application through the required Apple events. 
  4745. The Finder sends these required Apple events to your application to request the corresponding actions:
  4746. Apple event    Requested action    
  4747. Open Application    Perform tasks your application normally performs when a user opens your application without opening or printing any documents    
  4748. Open Documents    Open the specified documents     
  4749. Print Documents    Print the specified documents    
  4750. Quit Application    Perform tasks—such as releasing memory, requesting the user to save documents, and so on—associated with quitting before the Finder terminates your application    
  4751.  
  4752. In System 7 and later versions, the Finder uses these events as part of the mechanisms for launching and terminating applications. When the Finder launches your application, the application receives the Open Application, Open Documents, or Print Documents event. When the Finder terminates your application, the application receives the Quit Application event. This method of communicating Finder information to your application replaces the mechanisms used in earlier versions of system software.
  4753. Applications that do not support high-level events can still use the CountAppFiles, GetAppFiles, and ClrAppFiles procedures (or the GetAppParms procedure) to get the Finder information. See the chapter “Introduction to File Management” in Inside Macintosh: Files for information on these routines. To make your application compatible with System 7 and with earlier and later versions, you must support both the old and new mechanisms.
  4754. Use the Gestalt function to determine whether the Apple Event Manager is present. If it is and the isHighLevelEventAware flag is set in your application’s 'SIZE' resource, your application receives the Finder information through the required Apple events. 
  4755. If your application accepts high-level events, it must be able to process the four required Apple events. Your application receives the required Apple events from the Finder in these situations:
  4756. n    If your application is not open and the user opens your application from the Finder without opening or printing any documents, the Finder launches your application and sends it the Open Application event.
  4757. n    If your application is not open and the user opens one of your application’s documents from the Finder, the Finder launches your application and sends it the Open Documents event.
  4758. n    If your application is not open and the user prints one of your application’s documents from the Finder, the Finder launches your application and sends it the Print Documents event. Your application should print the selected documents and remain open until it receives a Quit Application event from the Finder.
  4759. n    If your application is open and the user opens or prints any of your application’s documents from the Finder, the Finder sends your application the Open Documents or Print Documents event.
  4760. n    If your application is open and the user chooses Restart or Shut Down from the Finder’s Special menu, the Finder sends your application the Quit Application event.
  4761. Upon receiving any of the required Apple events, your application should perform the action requested by the event. Here is a summary of the contents of the required events and the actions they request applications to perform:
  4762. Open Application—perform tasks associated with opening an application         
  4763. Event class    kCoreEventClass    
  4764. Event ID    kAEOpenApplication    
  4765. Parameters    None    
  4766. Requested action    Perform any tasks—such as opening an untitled document window—that you would normally perform when a user opens your application without opening or printing any documents.    
  4767.  
  4768. Open Documents—open the specified documents            
  4769. Event class        kCoreEventClass    
  4770. Event ID        kAEOpenDocuments    
  4771. Required parameter            
  4772.     Keyword:    keyDirectObject    
  4773.     Descriptor type:    typeAEList    
  4774.     Data:    A list of alias records for the documents to be opened    
  4775. Requested action        Open the documents specified in the keyDirectObject parameter.    
  4776.  
  4777. Print Documents—print the specified documents            
  4778. Event class        kCoreEventClass    
  4779. Event ID        kAEPrintDocuments    
  4780. Required parameter            
  4781.     Keyword:    keyDirectObject    
  4782.     Descriptor type:    typeAEList    
  4783.     Data:    A list of alias records for the documents to be printed    
  4784. Requested action        Print the documents specified in the keyDirectObject parameter without opening windows for the documents.     
  4785.  
  4786. Quit Application—perform tasks associated with quitting(continued)        
  4787. Event class    kCoreEventClass    
  4788. Event ID    kAEQuitApplication    
  4789. Parameters    None    
  4790. Requested action    Perform any tasks that your application would normally perform when the user chooses Quit. Such tasks typically include asking the user whether to save documents that have been changed. When appropriate, the Finder sends this event to an application immediately after sending it a Print Documents event (unless the application was already open) or if the user chooses Restart or Shut Down from the Finder’s Special menu.    
  4791.  
  4792. Your application needs to recognize only two descriptor types to handle the required Apple events: descriptor lists and alias records. The Open Documents event and Print Documents event use descriptor lists to store a list of documents to open. Each document is specified as an alias record in the descriptor list. 
  4793. You can retrieve the data that specifies the document to open as an alias record, or you can request that the Apple Event Manager coerce the alias record to a file system specification (FSSpec) record. The file system specification record provides a standard method of identifying files in System 7 and later versions. See Inside Macintosh: Files for a complete description of how to specify files using file system specification records.
  4794. Handling the Open Application Event
  4795.  
  4796. When the user opens your application, the Finder uses the Process Manager to launch your application. On startup, your application typically performs any needed initialization, and then begins to process events. If your application supports high-level events, and if the user opens your application without selecting any documents to open or print, your application receives the Open Application event.
  4797. To handle the Open Application event, your application should do just what the user expects it to do when it is opened. For example, your application might open a new untitled window in response to an Open Application event.
  4798. Listing 4-5 shows a handler that processes the Open Application event. This handler first calls an application-defined function called MyGotRequiredParams, which checks whether the Apple event contains any required parameters. If so, the handler returns an error, because by definition, the Open Application event should not contain any required parameters. Otherwise, the handler opens a new document window.
  4799. Listing 4-5    A handler for the Open Application event
  4800.  
  4801. FUNCTION MyHandleOApp (theAppleEvent, reply: AppleEvent; 
  4802.                                handlerRefcon: LongInt): OSErr;
  4803. VAR
  4804.     myErr: OSErr;
  4805. BEGIN
  4806.     myErr := MyGotRequiredParams(theAppleEvent);
  4807.     IF myErr = noErr THEN 
  4808.         DoNew;
  4809.     MyHandleOApp := myErr;
  4810. END;
  4811. For a description of the MyGotRequiredParams function, see Listing 4-11 on page 4-35. For information about the reply and handlerRefcon parameters for an Apple event handler, see “Writing Apple Event Handlers” on page 4-33. 
  4812. Handling the Open Documents Event
  4813.  
  4814. To handle the Open Documents event, your application should open the documents that the Open Documents event specifies in its direct parameter. Your application extracts this information and then opens the specified documents. Listing 4-6 shows a handler for the Open Documents event. 
  4815. Listing 4-6    A handler for the Open Documents event
  4816.  
  4817. FUNCTION MyHandleODoc (theAppleEvent, reply: AppleEvent;
  4818.                                   handlerRefcon: LongInt): OSErr;
  4819. VAR
  4820.     myFSS:                              FSSpec;
  4821.     docList:                              AEDescList;
  4822.     myErr, ignoreErr:                              OSErr;
  4823.     index, itemsInList:                            LongInt;
  4824.     actualSize:                              Size;
  4825.     keywd:                              AEKeyword;
  4826.     returnedType:                              DescType;
  4827. BEGIN
  4828.     {get the direct parameter--a descriptor list--and put it }
  4829.     { into docList}
  4830.     myErr := AEGetParamDesc(theAppleEvent, keyDirectObject,
  4831.                                     typeAEList, docList);
  4832.  
  4833.  
  4834.  
  4835.     IF myErr = noErr THEN 
  4836.     BEGIN
  4837.         {check for missing required parameters}
  4838.         myErr := MyGotRequiredParams(theAppleEvent);
  4839.         IF myErr = noErr THEN 
  4840.         BEGIN
  4841.             {count the number of descriptor records in the list}
  4842.             myErr := AECountItems (docList, itemsInList);
  4843.             IF myErr = noErr THEN
  4844.                 {now get each descriptor record from the list, }
  4845.                 { coerce the returned data to an FSSpec record, and }
  4846.                 { open the associated file}
  4847.                 FOR index := 1 TO itemsInList DO
  4848.                 BEGIN
  4849.                     myErr := AEGetNthPtr(docList, index, typeFSS, 
  4850.                                                 keywd, returnedType, @myFSS, 
  4851.                                                 Sizeof(myFSS),actualSize);
  4852.                     IF myErr = noErr THEN
  4853.                     BEGIN
  4854.                         myErr := MyOpenFile(@myFSS);
  4855.                         IF myErr <> noErr THEN 
  4856.                             ; {handle error from MyOpenFile}
  4857.                     END
  4858.                     ELSE
  4859.                         ; {handle error from AEGetNthPtr}
  4860.                 END; {of For index Do}
  4861.         END
  4862.         ELSE
  4863.             ; {handle error from MyGotRequiredParams}
  4864.         ignoreErr := AEDisposeDesc(docList);
  4865.     END
  4866.     ELSE
  4867.         ; {failed to get direct parameter, handle error}
  4868.     MyHandleODoc := myErr;
  4869. END;
  4870. The handler in Listing 4-6 first uses the AEGetParamDesc function to get the direct parameter (specified by the keyDirectObject keyword) out of the Apple event. The handler requests that AEGetParamDesc return a descriptor list in the docList variable. The handler then checks that it has retrieved all of the required parameters by calling the MyGotRequiredParams function. (See Listing 4-11 on page 4-35 for a description of this function.)
  4871. Once the handler has retrieved the descriptor list from the Apple event, it uses AECountItems to count the number of descriptors in the list. Using the returned number as an index, the handler can get the data of each descriptor record in the list. This handler requests that the AEGetNthPtr function coerce the data in the descriptor record to a file system specification record. The handler can then use the file system specification record as a parameter to its own routine for opening files.
  4872. For more information on the AEGetParamDesc function, see page 4-69. For more information on the AEGetNthPtr and AECountItems functions, see “Getting Data Out of a Descriptor List” on page 4-31.
  4873. After extracting the file system specification record that describes the document to open, your application can use this record to open the file. For example, in Listing 4-6, the code passes the file system specification record to its routine for opening files, the MyOpenFile function. 
  4874. The MyOpenFile function should be designed so that it can be called in response to both the Open Documents event and to events generated by the user. For example, when the user chooses Open from the File menu, the code that handles the mouse-down event uses the StandardGetFile procedure to let the user choose a file; it then calls MyOpenFile, passing the file system specification record returned by StandardGetFile. By isolating code that performs a requested action from code that interacts with the user, you can easily adapt your application to handle Apple events that request the same action. 
  4875. Note the use of the AEDisposeDesc function to dispose of the descriptor list when your handler no longer requires the data in it. Your handler should also return a result code.
  4876. Handling the Print Documents Event
  4877.  
  4878. To handle the Print Documents event, your application should extract information about the documents to be printed from the direct parameter, then print the specified documents. 
  4879. If your application can interact with the user, it should open windows for the documents, display a Print dialog box for the first document, and use the settings entered by the user for the first document to print all the documents. If user interaction is not allowed, your application may either return the error errAENoUserInteraction or print the documents using default settings. See “Interacting With the User,” which begins on page 4-45, for information about using the AEInteractWithUser function to interact with the user. 
  4880. Note that your application can remain open after processing the Print Documents event; when appropriate, the Finder sends your application a Quit Application event immediately after sending it a Print Documents event.
  4881. The handler for the Print Documents event shown in Listing 4-7 is similar to the handler for the Open Documents event, except that it prints the documents referred to in the direct parameter.
  4882. Listing 4-7    A handler for the Print Documents event
  4883.  
  4884. FUNCTION MyHandlePDoc (theAppleEvent, reply: AppleEvent;
  4885.                                handlerRefcon: LongInt): OSErr;
  4886. VAR
  4887.     myFSS:                              FSSpec;
  4888.     docList:                              AEDescList;
  4889.     myErr, ignoreErr:                              OSErr;
  4890.     index, itemsInList:                            LongInt;
  4891.     actualSize:                              Size;
  4892.     keywd:                              AEKeyword;
  4893.     returnedType:                              DescType;
  4894. BEGIN
  4895.     {get the direct parameter--a descriptor list--and put it }
  4896.     { into docList}
  4897.     myErr := AEGetParamDesc(theAppleEvent, keyDirectObject,
  4898.                                     typeAEList, docList);
  4899.     IF myErr = noErr THEN 
  4900.     BEGIN
  4901.         {check for missing required parameters}
  4902.         myErr := MyGotRequiredParams(theAppleEvent);
  4903.         IF myErr = noErr THEN 
  4904.         BEGIN
  4905.             {count the number of descriptor records in the list}
  4906.             myErr := AECountItems (docList, itemsInList);
  4907.             IF myErr = noErr THEN
  4908.                 {now get each descriptor record from the list, }
  4909.                 { coerce the returned data to an FSSpec record, and }
  4910.                 { print the associated file}
  4911.                 FOR index := 1 TO itemsInList DO
  4912.                 BEGIN
  4913.                     myErr := AEGetNthPtr(docList, index, typeFSS, 
  4914.                                                 keywd, returnedType, @myFSS, 
  4915.                                                 Sizeof(myFSS), actualSize);
  4916.                     IF myErr = noErr THEN
  4917.                     BEGIN
  4918.                         myErr := MyPrintFile(@myFSS);
  4919.                         IF myErr <> noErr THEN 
  4920.                             ; {handle error from MyOpenFile}
  4921.                     END
  4922.                     ELSE
  4923.                         ; {handle error from AEGetNthPtr}
  4924.                 END; {of For index Do}
  4925.         END
  4926.         ELSE
  4927.             ; {handle error from MyGotRequiredParams}
  4928.         ignoreErr := AEDisposeDesc(docList);
  4929.     END
  4930.     ELSE
  4931.         ; {failed to get direct parameter, handle error}
  4932.     MyHandlePDoc := myErr;
  4933. END;
  4934. Handling the Quit Application Event
  4935.  
  4936. To handle the Quit Application event, your application should take any actions that are necessary before it is terminated (such as saving any open documents). Listing 4-8 shows an example of a handler for the Quit Application event.
  4937. When appropriate, the Finder sends your application a Quit Application event immediately after a Print Documents event. The Finder also sends your application a Quit Application event if the user chooses Restart or Shut Down from the Finder’s Special menu. 
  4938. Listing 4-8    A handler for the Quit Application event
  4939.  
  4940. FUNCTION MyHandleQuit (theAppleEvent, reply: AppleEvent;
  4941.                                handlerRefcon: LongInt): OSErr;
  4942. VAR
  4943.     myErr:                    OSErr;
  4944.     userCanceled:                    Boolean;
  4945. BEGIN
  4946.     {check for missing required parameters}
  4947.     myErr := MyGotRequiredParams(theAppleEvent);
  4948.     IF myErr = noErr THEN 
  4949.     BEGIN
  4950.         userCanceled := MyPrepareToTerminate;
  4951.         IF userCanceled THEN
  4952.             MyHandleQuit := kUserCanceled
  4953.         ELSE
  4954.             MyHandleQuit := noErr;
  4955.     END
  4956.     ELSE
  4957.         MyHandleQuit := myErr;
  4958. END;
  4959. The handler in Listing 4-8 calls another function supplied by the application, the MyPrepareToTerminate function. This function saves the documents for any open windows and returns a Boolean value that indicates whether the user canceled the Quit operation. This is another example of isolating code for interacting with the user from the code that performs the requested action. By structuring your application in this way, you can use the same routine to respond to a user action (such as choosing the Quit command from the File menu) or to the corresponding Apple event. (For a description of the MyGotRequiredParams function, see “Writing Apple Event Handlers” on page 4-33.)
  4960. IMPORTANT
  4961. When your application is ready to quit, it should call the ExitToShell procedure from the main event loop, not from your handler for the Quit Application event. Your application should quit only after the handler returns noErr as its function result.s
  4962. Handling Apple Events Sent by the Edition Manager
  4963.  
  4964. If your application provides publish and subscribe capabilities, it should handle the Apple events sent by the Edition Manager in addition to the required Apple events. Your application should also handle the Create Publisher event, which is described in the “Handling the Create Publisher Event” section on page 4-22.
  4965. The Edition Manager sends your application Apple events to communicate information about the publishers and subscribers in your application’s documents. Specifically, the Edition Manager uses Apple events to notify your application 
  4966. n    when the information in an edition is updated
  4967. n    when your application needs to write the data from a publisher to an edition
  4968. n    when your application should locate a particular publisher and scroll through the document to that location
  4969. The Section Read, Section Write, and Section Scroll Events
  4970.  
  4971. The following descriptions identify the three Apple events sent by the Edition Manager—Section Read, Section Write, and Section Scroll—and the actions they tell applications to perform.
  4972. Section Read—read information into the specified section (continued)            
  4973. Event class        SectionEventMsgClass    
  4974. Event ID        SectionReadMsgID    
  4975. Required parameter            
  4976.     Keyword:    keyDirectObject    
  4977.     Descriptor type:    typeSectionH    
  4978.     Data:    A handle to the section record of the subscriber whose edition contains updated information    
  4979. Requested action        Update the subscriber with the new information from the edition.    
  4980.  
  4981. Section Write—write the specified section to an edition            
  4982. Event class        SectionEventMsgClass    
  4983. Event ID        SectionWriteMsgID    
  4984. Required parameter            
  4985.     Keyword:    keyDirectObject    
  4986.     Descriptor type:    typeSectionH    
  4987.     Data:    A handle to the section record of the publisher    
  4988. Requested action        Write the publisher’s data to its edition.    
  4989.  
  4990. Section Scroll—scroll through the document to the specified section            
  4991. Event class        SectionEventMsgClass    
  4992. Event ID        SectionScrollMsgID    
  4993. Required parameter            
  4994.     Keyword:    keyDirectObject    
  4995.     Descriptor type:    typeSectionH    
  4996.     Data:    A handle to the section record of the publisher to scroll to    
  4997. Requested action        Scroll through the document to the publisher identified by the specified section record.     
  4998.  
  4999. See the chapter “Edition Manager” in this book for details on how your application should respond to these events.
  5000. Handling the Create Publisher Event
  5001.  
  5002. If your application supports publish and subscribe capabilities, it should also handle the Create Publisher event.
  5003. Create Publisher—create a publisher            
  5004. Event class        kAEMiscStdSuite    
  5005. Event ID        kAECreatePublisher    
  5006. Required parameter        None    
  5007. Optional parameter            
  5008.     Keyword:    keyDirectObject    
  5009.     Descriptor type:    typeObjectSpecifier    
  5010.     Data:    An object specifier record that specifies the Apple event object or objects to publish. If this parameter is omitted, publish the current selection.    
  5011. Optional parameter            
  5012.     Keyword:    keyAEEditionFileLoc    
  5013.     Descriptor type:    typeAlias    
  5014.     Data:    An alias record that contains the location of the edition container to create. If this parameter is omitted, use the default edition container.    
  5015. Requested action        Create a publisher for the specified data using the specified loca-tion for the edition container. If the data isn’t specified, publish the current selection. If the location of the edition isn’t specified, use the default location.    
  5016.    
  5017. When your application receives the Create Publisher event, it should create a publisher and write the publisher’s data to an edition. The data of the publisher, and the location and name of the edition, are defined by the Apple event. If the Create Publisher event includes a keyDirectObject parameter, then your application should publish the data contained in the parameter. If the keyDirectObject parameter is missing, then your application should publish the current selection. If the document doesn’t have a current selection, your handler for the event should return a nonzero result code.
  5018. If the Create Publisher event includes a keyAEEditionFileLoc parameter, your application should use the location and name contained in the parameter as the default location and name of the edition. If the keyAEEditionFileLoc parameter is missing, your application should use the default location and name your application normally uses to specify the edition container.
  5019. Listing 4-9 shows a handler for the Create Publisher event. This handler checks for the keyDirectObject parameter and the keyAEEditionFileLoc parameter. If either of these is not specified, the handler uses default values. The handler uses the application-defined function DoNewPublisher to create the publisher and its edition, create a section record, and update other data structures associated with the document. See the chapter “Edition Manager” in this book for an example of the DoNewPublisher function.
  5020. Listing 4-9    A handler for the Create Publisher event
  5021.  
  5022. FUNCTION MyHandleCreatePublisherEvent (theAppleEvent,
  5023.                                                     reply: AppleEvent; 
  5024.                                                     handlerRefcon: LongInt)
  5025.                                                     : OSErr;
  5026. VAR        
  5027.     myErr:                                 OSErr;
  5028.     returnedType:                                DescType;
  5029.     thePublisherDataDesc:                                AEDesc;
  5030.     actualSize:                                 LongInt;
  5031.     promptForDialog:                                Boolean;
  5032.     thisDocument:                                 MyDocumentInfoPtr;
  5033.     preview:                                 Handle; 
  5034.     previewFormat:                                 FormatType; 
  5035.     defaultLocation:                                 EditionContainerSpec;
  5036. BEGIN
  5037.     MyGetDocumentPtr(thisDocument);
  5038.     myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, 
  5039.                                     typeObjectSpecifier, 
  5040.                                     thePublisherDataDesc);
  5041.     CASE myErr OF
  5042.         errAEDescNotFound: 
  5043.         BEGIN
  5044.             {use the current selection as the publisher and set up }
  5045.             { info for later when DoNewPublisher displays preview}
  5046.             preview := MyGetPreviewForSelection(thisDocument);
  5047.             previewFormat := 'TEXT';
  5048.         END;
  5049.         noErr: 
  5050.             {use the data in keyDirectObject parameter as the }
  5051.             { publisher (which is returned in the }
  5052.             { thePublisherDataDesc variable), and set up info for }
  5053.             { later when DoNewPublisher displays preview}
  5054.             MySetInfoForPreview(thePublisherDataDesc, thisDocument, 
  5055.                                        preview, previewFormat);
  5056.         OTHERWISE
  5057.         BEGIN
  5058.             MyHandleCreatePublisherEvent := myErr;
  5059.             Exit(MyHandleCreatePublisherEvent);
  5060.         END; 
  5061.     END;
  5062.     myErr := AEDisposeDesc(thePublisherDataDesc);
  5063.  
  5064.     myErr := AEGetParamPtr(theAppleEvent, keyAEEditionFileLoc, 
  5065.                                  typeFSS, returnedType, 
  5066.                                  @defaultLocation.theFile,
  5067.                                  SizeOf(FSSpec), actualSize);
  5068.     CASE myErr OF
  5069.         errAEDescNotFound: 
  5070.             {use the default location as the edition container}
  5071.                 myErr := MyGetDefaultEditionSpec(thisDocument, 
  5072.                                                             defaultLocation);
  5073.         noErr: 
  5074.         BEGIN                        {the keyAEEditionFileLoc parameter }
  5075.                                 { contains a default location}
  5076.             defaultLocation.thePart := kPartsNotUsed;
  5077.             defaultLocation.theFileScript := smSystemScript;
  5078.         END;
  5079.         OTHERWISE
  5080.         BEGIN
  5081.             MyHandleCreatePublisherEvent := myErr;
  5082.             Exit(MyHandleCreatePublisherEvent);
  5083.         END; 
  5084.     END;
  5085.     myErr := MyGotRequiredParams(theAppleEvent);
  5086.     IF myErr <> noErr THEN
  5087.     BEGIN
  5088.         MyHandleCreatePublisherEvent := myErr;
  5089.         Exit(MyHandleCreatePublisherEvent);
  5090.     END;
  5091.     myErr := AEInteractWithUser(kAEDefaultTimeout, gMyNotifyRecPtr, 
  5092.                                             @MyIdleFunction);
  5093.     IF myErr = noErr THEN promptForDialog := TRUE
  5094.                           ELSE promptForDialog := FALSE;
  5095.     myErr := DoNewPublisher(thisDocument, promptForDialog, 
  5096.                                     preview, previewFormat, 
  5097.                                     defaultLocation);
  5098.     {add keyErrorNumber and keyErrorString parameters if desired}
  5099. END;
  5100. Note that the MyHandleCreatePublisherEvent handler in Listing 4-9 uses the AEInteractWithUser function to determine whether user interaction is allowed. If so, the handler sets the promptForDialog variable to TRUE, indicating that the DoNewPublisher function should display the publisher dialog box. If not, 
  5101. the handler sets the promptForDialog variable to FALSE, and the DoNewPublisher function does not prompt the user for the location or name of the edition. For more information about AEInteractWithUser, see “Interacting With the User,” which begins on page 4-45.  
  5102. Getting Data Out of an Apple Event
  5103.  
  5104. The Apple Event Manager stores the parameters and attributes of an Apple event in a format that is internal to the Apple Event Manager. You use Apple Event Manager functions to retrieve the data from an Apple event and return it to your application in a format your application can use.
  5105. Most of the functions that retrieve data from Apple event parameters and attributes are available in two forms: one that returns the desired data in a specified buffer and one that returns a descriptor record containing the same data. For example, the AEGetParamPtr function uses a specified buffer to return the data contained in an Apple event parameter, and the AEGetParamDesc function returns the descriptor record for a specified parameter. 
  5106. You can also use Apple Event Manager functions to get data out of descriptor records, descriptor lists, and AE records. You use similar functions to put data into descriptor records, descriptor lists, and AE records.
  5107. When your handler receives an Apple event, you typically use the AEGetParamPtr, AEGetAttributePtr, AEGetParamDesc, or AEGetAttributeDesc function to get the data out of the Apple event.
  5108. Some Apple Event Manager functions let your application request that the data be returned using any descriptor type, even if it is different from the original descriptor type. If the original data is of a different descriptor type, the Apple Event Manager attempts to coerce the data to the requested descriptor type. 
  5109. For example, the AEGetParamPtr function lets you specify the desired descriptor type of the resulting data as follows:
  5110. VAR
  5111.     theAppleEvent:                        AppleEvent;
  5112.     returnedType:                         DescType;
  5113.     multResult:                        LongInt;
  5114.     actualSize:                         Size;
  5115.     myErr:                         OSErr;
  5116. myErr := AEGetParamPtr(theAppleEvent, keyMultResult, 
  5117.                               typeLongInteger, returnedType, 
  5118.                               @multResult, SizeOf(multResult),
  5119.                               actualSize);
  5120. In this example, the desired type is specified in the third parameter by the typeLongInteger descriptor type. This requests that the Apple Event Manager coerce the data to a long integer if it is not already of this type. To prevent coercion and ensure that the descriptor type of the result is of the same type as the original, specify typeWildCard for the third parameter.
  5121. The Apple Event Manager returns, in the returnedType parameter, the descriptor type of the resulting data. This is useful information when you specify typeWildCard as the desired descriptor type; you can determine the descriptor type of the resulting data by examining this parameter.
  5122. The Apple Event Manager can coerce many different types of data. For example, the Apple Event Manager can convert alias records to file system specification records, integers to Boolean data types, and characters to numeric data types, in addition to other data type conversions. For a complete list of the data types for which the Apple Event Manager provides coercion handling, see Table 4-1 on page 4-43.
  5123. To perform data coercions that the Apple Event Manager doesn’t perform, you can provide your own coercion handlers. See “Writing and Installing Coercion Handlers,” which begins on page 4-41, for information on providing your own coercion handlers.
  5124. Apple event parameters are keyword-specified descriptor records. You can use AEGetParamDesc to get the descriptor record of a parameter, or you can use AEGetParamPtr to get the data out of the descriptor record of a parameter. If an Apple event parameter consists of an object specifier record, you can use AEResolve and your own object accessor functions to resolve the object specifier record—that is, to locate the Apple event object it describes. For more information about AEResolve and object accessor functions, see “Writing Object Accessor Functions,” which begins on page 6-28. Attributes are also keyword-specified descriptor records, and you can use similar routines to get the descriptor record of an attribute or to get the data out of an attribute.
  5125. The following sections show how to use the AEGetParamPtr, AEGetAttributePtr, AEGetParamDesc, or AEGetAttributeDesc function to get the data out of an Apple event.
  5126. Getting Data Out of an Apple Event Parameter
  5127.  
  5128. You can use the AEGetParamPtr or AEGetParamDesc function to get the data out of an Apple event parameter. Use the AEGetParamPtr function (or the AEGetKeyPtr function, which works the same way) to return the data contained in a parameter. Use the AEGetParamDesc function when you need to get the descriptor record of a parameter or to extract the descriptor list from a parameter.
  5129. For example, suppose you need to get the data out of a Section Read event. The Edition Manager sends your application a Section Read event to tell your application to read updated information from an edition into the specified subscriber. The direct parameter of the Apple event contains a handle to the section record of the subscriber. You can use the AEGetParamPtr function to get the data out of the Apple event.
  5130. You specify the Apple event that contains the desired parameter, the keyword of the desired parameter, the descriptor type the function should use to return the data, a buffer to store the data, and the size of this buffer as parameters to the AEGetParamPtr function. The AEGetParamPtr function returns the descriptor type of the resulting data and the actual size of the data, and it places the requested data in the specified buffer.
  5131. VAR
  5132.     sectionH:                        SectionHandle;
  5133.     theAppleEvent:                        AppleEvent;
  5134.     returnedType:                         DescType;
  5135.     actualSize:                         Size;
  5136.     myErr:                         OSErr;
  5137. myErr := AEGetParamPtr(theAppleEvent, keyDirectObject, 
  5138.                               typeSectionH, returnedType, @sectionH, 
  5139.                               SizeOf(sectionH), actualSize);
  5140. In this example, the keyDirectObject keyword specifies that the AEGetParamPtr function should extract information from the direct parameter; AEGetParamPtr returns the data in the buffer specified by the sectionH variable. 
  5141. You can request that the Apple Event Manager return the data using the descriptor type of the original data or you can request that the Apple Event Manager coerce the data into a descriptor type that is different from the original. To prevent coercion, specify the desired descriptor type as typeWildCard.
  5142. The typeSectionH descriptor type specifies that the returned data should be coerced to a handle to a section record. You can use the information returned in the sectionH variable to identify the subscriber and read in the information from the edition.
  5143. In this example, the AEGetParamPtr function returns, in the returnedType variable, the descriptor type of the resulting data. The descriptor type of the resulting data matches the requested descriptor type unless the Apple Event Manager wasn’t able to coerce the data to the specified descriptor type or you specified the desired descriptor type as typeWildCard. If the coercion fails, the Apple Event Manager returns the errAECoercionFail result code.
  5144. The AEGetParamPtr function returns, in the actualSize variable, the actual size of the data (that is, the size of coerced data, if any coercion was performed). If the value returned in this variable is greater than the amount your application allocated for the buffer to hold the returned data, your application can increase the size of its buffer to this amount, and get the data again. You can also choose to use the AEGetParamDesc function when your application doesn’t know the size of the data.
  5145. In general, use the AEGetParamPtr function to extract data that is of fixed length or known maximum length, and the AEGetParamDesc function to extract data that is of variable length. The AEGetParamDesc function returns the descriptor record for an Apple event parameter. This function is useful, for example, for extracting a descriptor list from a parameter. 
  5146. You specify, as parameters to AEGetParamDesc, the Apple event that contains the desired parameter, the keyword of the desired parameter, the descriptor type the function should use to return the descriptor record, and a buffer to store the returned descriptor record. The AEGetParamDesc function returns the descriptor record using the specified descriptor type. 
  5147. For example, the direct parameter of the Open Documents event contains a descriptor list that specifies the documents to open. You can use the AEGetParamDesc function to get the descriptor list out of the direct parameter.
  5148. VAR
  5149.     docList:                        AEDescList;
  5150.     theAppleEvent:                        AppleEvent;
  5151.     myErr:                         OSErr;
  5152. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject, 
  5153.                                 typeAEList, docList);
  5154. In this example, the Apple event specified by the variable theAppleEvent contains the desired parameter. The keyDirectObject keyword specifies that the AEGetParamDesc function should get the descriptor record of the direct parameter. The typeAEList descriptor type specifies that the descriptor record should be returned as a descriptor list. In this example, the AEGetParamDesc function returns a descriptor list in the docList variable.
  5155. The descriptor list contains a list of descriptor records. To get the descriptor records and their data out of a descriptor list, use the AECountItems function to find the number of descriptor records in the list and then make repetitive calls to the AEGetNthPtr function to get the data out of each descriptor record. See “Getting Data Out of a Descriptor List” on page 4-31 for more information.
  5156. Note that the AEGetParamDesc function copies the descriptor record from the parameter. When you’re done with a descriptor record that you obtained from AEGetParamDesc, you must dispose of it by calling the AEDisposeDesc function.
  5157. If an Apple event parameter consists of an object specifier record, you can use AEResolve to resolve the object specifier record (that is, locate the Apple event object it describes), as explained in “Finding Apple Event Objects” on page 3-46.
  5158. Getting Data Out of an Attribute
  5159.  
  5160. You can use the AEGetAttributePtr or AEGetAttributeDesc function to get the data out of the attributes of an Apple event. 
  5161. You specify, as parameters to AEGetAttributePtr, the Apple event that contains the desired attribute, the keyword of the desired attribute, the descriptor type the function should use to return the data, a buffer to store the data, and the size of this buffer. The AEGetAttributePtr function returns the descriptor type of the returned data and the actual size of the data and places the requested data in the specified buffer.
  5162. For example, this code gets the data out of the keyEventSourceAttr attribute of an Apple event.
  5163. VAR
  5164.     theAppleEvent:                        AppleEvent;
  5165.     returnedType:                         DescType;
  5166.     sourceOfAE:                        Integer;
  5167.     actualSize:                        Size;
  5168.     myErr:                         OSErr;
  5169. myErr := AEGetAttributePtr(theAppleEvent, keyEventSourceAttr, 
  5170.                                      typeShortInteger, returnedType, 
  5171.                                     @sourceOfAE, SizeOf(sourceOfAE), 
  5172.                                     actualSize); 
  5173. The keyEventSourceAttr keyword specifies the attribute from which to get the data. The typeShortInteger descriptor type specifies that the data should be returned as a short integer; the returnedType variable contains the actual descriptor type that is returned. You also must specify a buffer to hold the returned data and specify the size of this buffer. If the data is not already a short integer, the Apple Event Manager coerces it as necessary before returning it. The AEGetAttributePtr function returns, in the actualSize variable, the actual size of the returned data after coercion has taken place. You can check this value to make sure you got all the data.
  5174. As with the AEGetParamPtr function, you can request that AEGetAttributePtr return the data using the descriptor type of the original data, or you can request that the Apple Event Manager coerce the data into a descriptor type that is different from the original. 
  5175. In this example, the AEGetAttributePtr function returns the requested data as a short integer in the sourceOfAE variable, and you can get information about the source of the Apple event by examining this value. You can test the returned value against the values defined by the data type AEEventSource.
  5176. TYPE AEEventSource = (kAEUnknownSource, kAEDirectCall, 
  5177.                              kAESameProcess, kAELocalProcess, 
  5178.                              kAERemoteProcess);
  5179. The constants defined by the data type AEEventSource have the following meanings:
  5180. Constant     Meaning    
  5181. kAEUnknownSource    Source of Apple event unknown    
  5182. kAEDirectCall    A direct call that bypassed the PPC Toolbox    
  5183. kAESameProcess    Target application is also the source application    
  5184. kAELocalProcess    Source application is another process on the same computer as the target application    
  5185. kAERemoteProcess    Source application is a process on a remote computer on the network    
  5186.  
  5187. The next example shows how to use the AEGetAttributePtr function to get data out of the keyMissedKeywordAttr attribute. After your handler extracts all known parameters from an Apple event, it should check whether the keyMissedKeywordAttr attribute exists. If it does, then your handler did not get all of the required parameters.
  5188. Note that if AEGetAttributePtr returns the errAEDescNotFound result code, then the keyMissedKeywordAttr attribute does not exist—that is, your application has extracted all of the required parameters. If AEGetAttributePtr returns noErr, then the keyMissedKeywordAttr attribute does exist—that is, your handler did not get all of the required parameters.
  5189. myErr := AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, 
  5190.                                     typeWildCard, returnedType, NIL, 0, 
  5191.                                     actualSize);
  5192. The data in the keyMissedKeywordAttr attribute contains the keyword of the first required parameter, if any, that your handler didn’t retrieve. If you want this data returned, specify a buffer to hold it and specify the buffer size. Otherwise, as in this example, specify NIL as the buffer and 0 as the size of the buffer.
  5193. This example shows how to use the AEGetAttributePtr function to get the address of the sender of an Apple event from the keyAddressAttr attribute of the Apple event:
  5194. VAR
  5195.     theAppleEvent:     AppleEvent;
  5196.     returnedType:                     DescType;
  5197.     addressOfAE:                     TargetID;
  5198.     actualSize:                     Size;
  5199.     myErr:                     OSErr;
  5200.  
  5201. myErr := AEGetAttributePtr(theAppleEvent, keyAddressAttr, 
  5202.                                     typeTargetID, returnedType, 
  5203.                                     @addressOfAE, SizeOf(addressOfAE), 
  5204.                                     actualSize);
  5205. The keyAddressAttr keyword specifies the attribute to get the data from. The typeTargetID descriptor type specifies that the data should be returned as a target ID record; the returnedType variable contains the actual descriptor type that is returned. You can examine the address returned in the addressOfAE variable to determine the sender of the Apple event.
  5206. The target ID record returned in the addressOfAE variable contains the sender’s port name, port location, and session reference number. To get the process serial number for a process on the local machine, pass the port name returned in the target ID record to the GetProcessSerialNumberFromPortName function. You can then pass the process serial number to the GetProcessInformation function to find the creator signature for a given process. (For more information about these functions, see the chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials.)
  5207. For more information about target addresses, see “Specifying a Target Address” on page 5-10.
  5208. Getting Data Out of a Descriptor List
  5209.  
  5210. You can use the AECountItems function to count the number of items in a descriptor list, and you can use AEGetNthDesc or AEGetNthPtr to get a descriptor record or its data out of a descriptor list.
  5211. The Open Documents event contains a direct parameter that specifies the list of documents to open. The list of documents is contained in a descriptor list. After extracting the descriptor list from the parameter, you can determine the number of items in the list and then extract each descriptor record from the descriptor list. See Figure 3-9 on page 3-19 for a depiction of the Open Documents event.
  5212. For example, when your handler receives an Open Documents event, you can use the AEGetParamDesc function to return the direct parameter as a descriptor list. You can then use AECountItems to return the number of descriptor records in the list.
  5213. VAR
  5214.     theAppleEvent:                        AppleEvent;
  5215.     docList:                        AEDescList;
  5216.     itemsInList:                        LongInt;
  5217.     myErr:                        OSErr;
  5218. myErr := AEGetParamDesc(theAppleEvent, keyDirectObject,
  5219.                                 typeAEList, docList);
  5220. myErr := AECountItems(docList, itemsInList);
  5221. The AEGetParamDesc function returns, in the docList variable, a copy of the descriptor list from the direct parameter of the Open Documents event. You specify this list to the AECountItems function.
  5222. You specify the descriptor list whose items you want to count in the first parameter to AECountItems. The Apple Event Manager returns, in the second parameter, the number of items in the list. When extracting the descriptor records from a list, you often use the number of items as a loop index. Here’s an example:
  5223. FOR index := 1 TO itemsInList DO
  5224.     BEGIN
  5225.     {for each descriptor record in the list, get its data}
  5226.     END;
  5227. The format of the descriptor records in a descriptor list is private to the Apple Event Manager. You must use the AEGetNthPtr or AEGetNthDesc function to extract descriptor records from a descriptor list.  
  5228. You specify the descriptor list that contains the desired descriptor records and an index as parameters to the AEGetNthPtr function. The index represents a specific descriptor record in the descriptor list. The AEGetNthPtr function returns the data for the descriptor record represented by the specified index. 
  5229. You also specify the descriptor type the function should use to return the data, a buffer to store the data, and the size of this buffer. If the specified descriptor record exists, the AEGetNthPtr function returns the keyword of the parameter, the descriptor type of the returned data, and the actual size of the data, and it places the requested data in the specified buffer.
  5230. Here’s an example that uses the AEGetNthPtr function to extract an item from the descriptor list in the direct parameter of the Open Documents event:
  5231. myErr := AEGetNthPtr(docList, index, typeFSS, keywd, 
  5232.                             returnedType, @myFSS, Sizeof(myFSS), 
  5233.                             actualSize);
  5234. The docList variable specifies the descriptor list from the direct parameter of the Open Documents event. The index variable specifies the index of the descriptor record to extract. You can use the typeFSS descriptor type, as in this example, to specify that the data be returned as a file system specification record. The Apple Event Manager automatically coerces the original data type of the descriptor record from an alias record to a file system specification record. The AEGetNthPtr function returns the keyword of the parameter and the descriptor type of the resulting data in the keywd and returnedType variables, respectively. 
  5235. You also specify a buffer to hold the desired data and the size (in bytes) of the buffer. In this example, the myFSS variable specifies the buffer. The function returns the actual size of the data in the actualSize variable. If this size is larger than the size of the buffer you provided, you know that you didn’t get all of the data for the descriptor record.
  5236. Listing 4-10 shows a more complete example of extracting the items from a descriptor list in the Open Documents event.
  5237. Listing 4-10    Extracting items from a descriptor list
  5238.  
  5239. VAR
  5240.     index:                        LongInt;
  5241.     itemsInList:                         LongInt;
  5242.     docList:                        AEDescList;
  5243.     keywd:                         AEKeyword;
  5244.     returnedType:                         DescType;
  5245.     myFSS:                        FSSpec;
  5246.     actualSize:                         Size;
  5247.     myErr:                         OSErr;
  5248.  
  5249. FOR index := 1 TO itemsInList DO
  5250.     BEGIN
  5251.         myErr := AEGetNthPtr(docList, index, typeFSS, keywd, 
  5252.                                     returnedType, @myFSS, Sizeof(myFSS), 
  5253.                                     actualSize);
  5254.         IF myErr <> noErr THEN DoError(myErr);
  5255.         myErr := MyOpenFile(@myFSS);
  5256.         IF myErr <> noErr THEN DoError(myErr);
  5257.     END;
  5258. myErr := AEDisposeDesc(docList);  
  5259. Writing Apple Event Handlers
  5260.  
  5261. For each Apple event your application supports, you must provide a function called an Apple event handler. The AEProcessAppleEvent function calls one of your Apple event handlers when it processes an Apple event. Your Apple event handlers should perform any action requested by the Apple event, add parameters to the reply Apple event if appropriate, and return a result code.
  5262. The Apple Event Manager uses dispatch tables to route Apple events to the appropriate Apple event handler. You must supply an Apple event handler for each entry in your application’s Apple event dispatch table. Each handler must be a function that uses this syntax:
  5263. FUNCTION MyEventHandler (theAppleEvent: AppleEvent; 
  5264.                                  reply: AppleEvent; 
  5265.                                  handlerRefcon: LongInt): OSErr; 
  5266. The parameter theAppleEvent is the Apple event to handle. Your handler uses Apple Event Manager functions to extract any parameters and attributes from the Apple event and then performs the necessary processing. If any of the parameters include object specifier records, your handler should call AEResolve to resolve them—that is, to locate the Apple event objects they describe. For more information, see the chapter “Resolving and Creating Object Specifier Records” in this book.
  5267. The reply parameter is the default reply provided by the Apple Event Manager. (“Replying to an Apple Event,” which begins on page 4-36, describes how to add parameters to the default reply.) The handlerRefcon parameter is the reference constant stored in the Apple event dispatch table entry for the Apple event. Your handler can check the reference constant, if necessary, for information about the Apple event.
  5268. You can use the reference constant for anything you wish. For example, if you want to use the same handler for several Apple events, you can install entries for each event in your application’s Apple event dispatch table that specify the same handler but different reference constants. Your handler can then use the reference constant to distinguish the different Apple events it handles.
  5269. To provide an Apple event handler in C, be sure to include the Pascal declaration before the handler declaration. This is the syntax for an Apple event handler in C: 
  5270. pascal OSErr MyEventHandler (const AppleEvent *theAppleEvent, 
  5271.                                       const AppleEvent *reply, 
  5272.                                       long handlerRefcon);
  5273. After extracting all known parameters from the Apple event, every handler should determine whether the Apple event contains any further required parameters. Your handler can determine whether it retrieved all the required parameters by checking whether the keyMissedKeywordAttr attribute exists. If the attribute exists, then your handler has not retrieved all the required parameters and should immediately return an error. If the attribute does not exist, then the Apple event does not contain any more required parameters, although it may contain additional optional parameters.
  5274. The Apple Event Manager determines which parameters are optional according to the keywords listed in the keyOptionalKeywordAttr attribute. The source application is responsible for adding these keywords to the keyOptionalKeywordAttr attribute, but is not required to do so, even if that parameter is listed in the Apple Event Registry: Standard Suites as an optional parameter. If the source application does not add the necessary keyword to the keyOptionalKeywordAttr attribute, the target application treats the parameter as required for that Apple event. If the target application supports the parameter, it should handle the Apple event as the source application expects. If the target application does not support the parameter and checks whether it has received all the required parameters, it finds that there’s another parameter that the client application considered required, and should return the result code errAEParamMissed without attempting to handle the event. 
  5275. Listing 4-11 shows a function that checks for a keyMissedKeywordAttr attribute. A handler calls this function after getting all the required parameters it knows about from an Apple event.
  5276. Listing 4-11    A function that checks for a keyMissedKeywordAttr attribute
  5277.  
  5278. FUNCTION MyGotRequiredParams (theAppleEvent: AppleEvent): OSErr;
  5279. VAR
  5280.     myErr:                        OSErr;
  5281.     returnedType:                        DescType;
  5282.     actualSize:                        Size;
  5283. BEGIN
  5284.     myErr := AEGetAttributePtr(theAppleEvent, 
  5285.                                          keyMissedKeywordAttr, 
  5286.                                            typeWildCard, returnedType, 
  5287.                                          NIL, 0, actualSize);
  5288.     IF myErr = errAEDescNotFound THEN                                             
  5289.         {you got all the required parameters}
  5290.         MyGotRequiredParams := noErr
  5291.     ELSE IF myErr = noErr THEN                                              
  5292.         {you missed a required parameter}
  5293.         MyGotRequiredParams := errAEParamMissed;
  5294. END;
  5295. The code in Listing 4-11 uses the AEGetAttributePtr function to get the keyMissedKeywordAttr attribute. This attribute contains the first required parameter, if any, that your handler didn’t retrieve. If AEGetAttributePtr returns the errAEDescNotFound result code, the Apple event doesn’t contain a keyMissedKeywordAttr attribute. If the Apple event doesn’t contain this attribute, then your handler has extracted all of the parameters that the client application considered required. 
  5296. If the AEGetAttributePtr function returns noErr as the result code, then the attribute does exist, meaning that your handler has not extracted all of the required parameters. In this case, your handler should return an error and not process the Apple event.
  5297. The first remaining required parameter is specified by the data of the keyMissedKeywordAttr attribute. If you want this data returned, specify a buffer to hold the data. Otherwise, specify NIL as the buffer and 0 as the size of the buffer. If you specify a buffer to hold the data, you can check the value of the actualSize parameter to see if the data is larger than the buffer you allocated.
  5298. For more information about specifying Apple event parameters as optional or required, see “Specifying Optional Parameters for an Apple Event” beginning on page 5-7. 
  5299. Replying to an Apple Event
  5300.  
  5301. Your handler routine for a particular Apple event is responsible for performing the action requested by the Apple event, and can optionally return data in a reply Apple event. The Apple Event Manager passes a default reply Apple event to your handler. The default reply Apple event has no parameters when it is passed to your handler. Your handler can add parameters to the reply Apple event. If the client application requested a reply, the Apple Event Manager returns the reply Apple event to the client. 
  5302. The reply Apple event is identified by the kCoreEventClass event class and by the kAEAnswer event ID. If the client application specified the kAENoReply flag in the reply parameter of the AESend function, the Apple Event Manager passes a null descriptor record (a descriptor record of type typeNull whose data handle has the value NIL) to your handler instead of a default reply Apple event. Your handler should check the descriptor type of the reply Apple event before attempting to add any attributes or parameters to it. An attempt to add an Apple event attribute or parameter to a null descriptor record generates an error. 
  5303. If the client application requests a reply, the Apple Event Manager prepares a reply Apple event for the client by passing a default reply Apple event to your handler. The default reply Apple event has no parameters when it is passed to your handler. Your handler can add any parameters to the reply Apple event. If your application is a spelling checker, for example, you can return a list of misspelled words in a parameter. 
  5304. When your handler finishes processing an Apple event, it returns a result code to AEProcessAppleEvent, which returns this result code as its function result. If your handler returns a nonzero result code, and if you have not added your own keyErrorNumber parameter, the Apple Event Manager also returns this result code to the client application by putting the result code into a keyErrorNumber parameter for the reply Apple event. The client can check for the existence of this parameter to determine whether the handler performed the requested action.
  5305. The client application specifies whether it wants a reply Apple event or not by specifying flags (represented by constants) in the sendMode parameter of the AESend function.
  5306. If the client specifies the kAEWaitReply flag in the sendMode parameter, the AESend function does not return until the timeout specified by the timeoutInTicks parameter expires or the server application returns a reply. When the server application returns a reply, the reply parameter to AESend contains the reply Apple event that your handler returned to the AEProcessAppleEvent function. When the client application no longer needs the original Apple event and the reply event, it must dispose of them, but the Apple Event Manager disposes of both the Apple event and the reply event for the server application when the server’s handler returns to AEProcessAppleEvent.  
  5307. If the client specified the kAEQueueReply flag, the client receives the reply event at a later time during its normal processing of other events. 
  5308. Your handler should always set its function result to noErr if it successfully 
  5309. handles the Apple event. If an error occurs, your handler should return either errAEEventNotHandled or some other nonzero result code. If the error 
  5310. occurs because your application cannot understand the event, return errAEEventNotHandled. This allows the Apple Event Manager to look for a handler in the system special handler or system Apple event dispatch tables that might be able to handle the event. If the error occurs because the event is impossible to handle as specified, return the result code returned by whatever function caused the failure, or whatever other result code is appropriate.
  5311. For example, suppose your application receives a Get Data event requesting the name of the current printer, and your application cannot handle such an event. In this situation, you should return errAEEventNotHandled in case another handler available to the Apple Event Manager can handle the Get Data event. This strategy allows users to take advantage of system capabilities from within your application via system handlers. 
  5312. However, if your application cannot handle a Get Data event that requests the fifth paragraph in a document because the document contains only four paragraphs, you should return some other nonzero error, because further attempts to handle the event are pointless.
  5313. If your Apple event handler calls the AEResolve function and AEResolve calls an object accessor function in the system object accessor dispatch table, your Apple event handler may not recognize the descriptor type of the token returned by the function. In this case, your handler should return the result code errAEUnknownObjectType. When your handler returns this result code, the Apple Event Manager attempts to locate a system Apple event handler that can recognize the token. For more information, see “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 6-21.
  5314. The Apple Event Manager automatically adds any nonzero result code that your handler returns to a keyErrorNumber parameter in the reply Apple event. In addition to returning a result code, your handler can also return an error string in the keyErrorString parameter of the reply Apple event. Your handler should provide meaningful text in the keyErrorString parameter, so that the client can display this string to the user if desired. 
  5315. Listing 4-12 shows how to add the keyErrorString parameter to the reply Apple event. See “Adding Parameters to an Apple Event” on page 5-5 for a description of the AEPutParamPtr function.
  5316. Listing 4-12    Adding the keyErrorString parameter to the reply Apple event
  5317.  
  5318. FUNCTION MyHandler (theAppleEvent: AppleEvent; reply: AppleEvent;
  5319.                           handlerRefcon: LongInt): OSErr; 
  5320. VAR
  5321.     myErr:                OSErr;
  5322.     errStr:                Str255;
  5323. BEGIN
  5324.     {handle your Apple event here}
  5325.  
  5326.     {if an error occurs when handling an Apple event, set the }
  5327.     { function result and error string accordingly}
  5328.     IF myErr <> noErr THEN
  5329.     BEGIN
  5330.         MyHandler := myErr;     {result code to be returned--the }
  5331.                                     { Apple Event Manager adds this }
  5332.                                     { result code to the reply Apple }
  5333.                                     { event as the keyErrorNumber }
  5334.                                     { parameter}
  5335.         IF (reply.dataHandle <> NIL) THEN
  5336.         {add error string parameter to the default reply}
  5337.         BEGIN
  5338.             {strings should normally be stored in resources}
  5339.             errStr := 'Why error occurred';
  5340.             myErr := AEPutParamPtr(reply, keyErrorString, 
  5341.                                             typeIntlText, @errStr[1], 
  5342.                                             length(errStr));
  5343.         END;
  5344.     END
  5345.     ELSE
  5346.         MyHandler := noErr;
  5347. END;
  5348. If your handler needs to return data to the client, it can add parameters to the reply Apple event. Listing 4-13 shows how a handler for the Multiply event (an imaginary Apple event that asks the server to multiply two numbers) might return the results of the multiplication to the client.
  5349. Listing 4-13    Adding parameters to the reply Apple event
  5350.  
  5351. FUNCTION MyMultHandler (theAppleEvent: AppleEvent; 
  5352.                                 reply: AppleEvent; 
  5353.                                 handlerRefcon: LongInt): OSErr; 
  5354. VAR
  5355.     myErr:                        OSErr;
  5356.     number1,number2:                        LongInt;
  5357.     replyResult:                        LongInt;
  5358.     actualSize:                        Size;
  5359.     returnedType:                        DescType;
  5360. BEGIN
  5361.     {get the numbers to multiply from the parameters of the }
  5362.     { Apple event; put the numbers in the number1 and number2 }
  5363.     { variables and then perform the requested multiplication}
  5364.     myErr := MyDoMultiply(theAppleEvent, number1, 
  5365.                                     number2, replyResult);
  5366.     IF myErr = noErr THEN 
  5367.         IF (reply.dataHandle <> NIL) THEN
  5368.             {return result of the multiplication in the reply Apple }
  5369.             { event}
  5370.             myErr := AEPutParamPtr(reply, keyDirectObject, 
  5371.                                             typeLongInteger, @replyResult, 
  5372.                                             SizeOf(replyResult));
  5373.     MyMultHandler := myErr;
  5374.     {if an error occurs, set the error string }
  5375.     { accordingly, as shown in Listing 4-12}
  5376. END;
  5377. Disposing of Apple Event Data Structures
  5378.  
  5379. Whenever a client application uses Apple Event Manager functions to create a descriptor record, descriptor list, or Apple event record, the Apple Event Manager allocates memory for these data structures in the client’s application heap. Likewise, when a server application extracts a descriptor record from an Apple event by using Apple Event Manager functions, the Apple Event Manager creates a copy of the descriptor record, including the data to which its handle refers, in the server’s application heap.
  5380. Whenever you finish using a descriptor record or descriptor list that you have created or extracted from an Apple event, you should dispose of the descriptor record—and thereby deallocate the memory it uses—by calling the AEDisposeDesc function. If the descriptor record you pass to AEDisposeDesc (such as an Apple event record or an AE record) includes other nested descriptor records, one call to AEDisposeDesc will dispose of them all. 
  5381. When a client application adds a descriptor record to an Apple event (for example, when it creates a descriptor record by calling AECreateDesc and then puts a copy of it into a parameter of an Apple event by calling AEPutParamDesc), it is still responsible for disposing of the original descriptor record. After a client application has finished using both the Apple event specified in the AESend function and the reply Apple event, it should dispose of their descriptor records by calling AEDisposeDesc. The client application should dispose of them even if AESend returns a nonzero result code. 
  5382. The Apple event that a server application’s handler receives is a copy of the original event created by the client application. When a server application’s handler returns to AEProcessAppleEvent, the Apple Event Manager disposes of the server’s copy (in the server’s application heap) of both the Apple event and the reply event. The server application is responsible for disposing of any descriptor records created while extracting data from the Apple event or adding data to the reply event.
  5383. In general, outputs from Apple Event Manager functions are your application’s responsibility. Once you finish using them, you should use AEDisposeDesc to dispose of any Apple event data structures created or returned by these functions:AECoerceDesc    AEDuplicateDesc    
  5384. AECoercePtr    AEGetAttributeDesc    
  5385. AECreateAppleEvent    AEGetKeyDesc    
  5386. AECreateDesc    AEGetNthDesc    
  5387. AECreateList    AEGetParamDesc    
  5388.  
  5389. If you attempt to dispose of descriptor records returned by successful calls to these functions without using AEDisposeDesc, your application may not be compatible with future versions of the Apple Event Manager. However, if any of these functions return a nonzero result code, they return a null descriptor record, which does not need to be disposed of. 
  5390. Outputs from functions, such as AEGetKeyPtr, that use a buffer rather than a descriptor record to return data do not require the use of AEDisposeDesc. It is therefore preferable to use these functions for any data that is not identified by a handle. 
  5391. Some of the functions described in the chapter “Resolving and Creating Object Specifier Records” in this book also create descriptor records. If you set the disposeInputs parameter to FALSE for any of the following functions, you should dispose of any Apple event data structures that they create or return:CreateCompDescriptor    CreateObjSpecifier    
  5392. CreateLogicalDescriptor    CreateRangeDescriptor     
  5393.  
  5394. Your application is also responsible for disposing of some of the tokens it creates in the process of resolving an object specifier record. For information about token disposal, see “Defining Tokens” on page 6-39. 
  5395. Writing and Installing Coercion Handlers
  5396.  
  5397. When your application extracts data from a parameter, it can request that the Apple Event Manager return the data using a descriptor type that is different from the original descriptor type. For example, when extracting data from the direct parameter of the Open Documents event, you can request that the alias records be returned as file system specification records. The Apple Event Manager can automatically coerce many different types of data from one to another. Table 4-1 on page 4-43 shows descriptor types and the kinds of coercion that the Apple Event Manager can perform.
  5398. You can also provide your own routines, referred to as coercion handlers, to coerce data into any other descriptor type. To install your own coercion handlers, use the AEInstallCoercionHandler function. You specify as parameters to this function
  5399. n    the descriptor type of the data coerced by the handler
  5400. n    the descriptor type of the resulting data
  5401. n    the address of the coercion handler for this descriptor type
  5402. n    a reference constant
  5403. n    a Boolean value that indicates whether your coercion handler expects the data to be specified as a descriptor record or as a pointer to the actual data
  5404. n    a Boolean value that indicates whether your coercion handler should be added to your application’s coercion dispatch table or the system coercion dispatch table
  5405. The system coercion dispatch table is a table in the system heap that contains coercion handlers available to all applications and processes running on the same computer. The coercion handlers in your application’s coercion dispatch table are available only to your application. When attempting to coerce data, the Apple Event Manager first looks for a coercion handler in your application’s coercion dispatch table. If it cannot find a handler for the descriptor type, it looks in the system coercion dispatch table for a handler. If it doesn’t find a handler there, it attempts to use the default coercion handling described by Table 4-1 on page 4-43. If it can’t find an appropriate default coercion handler, it returns the errAECoercionFail result code. 
  5406. Any handler that you add to the system coercion dispatch table should reside in the system heap. If there was already an entry in the system coercion dispatch table for the same descriptor type, it is replaced. Therefore, if there is an entry in the system coercion dispatch table for the same descriptor type, you should chain it to your system coercion handler as explained in “Creating and Managing the Coercion Handler Dispatch Tables,” which begins on page 4-96.
  5407. sWARNING
  5408. Before an application calls a system coercion handler, system software has set up the A5 register for the calling application. For this reason, if you provide a system coercion handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system coercion handler may crash.s
  5409. You can provide a coercion handler that expects to receive the data in a descriptor record or a buffer referred to by a pointer. When you install your coercion handler, you specify how your handler wishes to receive the data. Whenever possible, you should write your coercion handler so that it can accept a pointer to the data, because it’s more efficient for the Apple Event Manager to provide your coercion handler with a pointer to the data.
  5410. A coercion handler that accepts a pointer to data must be a function with the following syntax:
  5411. FUNCTION MyCoercePtr (typeCode: DescType; dataPtr: Ptr; 
  5412.                              dataSize: Size; toType: DescType; 
  5413.                              handlerRefcon: LongInt;
  5414.                              VAR result: AEDesc): OSErr; 
  5415. The typeCode parameter is the descriptor type of the original data. The dataPtr parameter is a pointer to the data to coerce; the dataSize parameter is the length, in bytes, of the data. The toType parameter is the desired descriptor type of the resulting data. The handlerRefcon parameter is a reference constant stored in the coercion table entry for the handler and passed to the handler by the Apple Event Manager whenever the handler is called. The result parameter is the descriptor record returned by your coercion handler.
  5416. Your coercion handler should coerce the data to the desired descriptor type and return the data in the descriptor record specified by the result parameter. If your handler successfully performs the coercion, it should return the noErr result code; otherwise, it should return a nonzero result code.
  5417. A coercion handler that accepts a descriptor record must be a function with the following syntax:
  5418. FUNCTION MyCoerceDesc (theAEDesc: AEDesc; toType: DescType;
  5419.                               handlerRefcon: LongInt;
  5420.                               VAR result: AEDesc): OSErr;
  5421. The parameter theAEDesc is the descriptor record that contains the data to be coerced. The toType parameter is the descriptor type of the resulting data. The handlerRefcon parameter is a reference constant stored in the coercion table entry for the handler and passed to the handler by the Apple Event Manager whenever the handler is called. The result parameter is the resulting descriptor record.
  5422. Your coercion handler should coerce the data in the descriptor record to the desired descriptor type and return the data in the descriptor record specified by the result parameter. Your handler should return an appropriate result code.
  5423. Note
  5424. To ensure that no coercion is performed and that the descriptor type of the result is of the same descriptor type as the original, specify typeWildCard for the desired type.u
  5425. Table 4-1 lists the descriptor types for which the Apple Event Manager provides coercion. 
  5426. Table 4-1    Coercion handling provided by the Apple Event Manager(continued)
  5427. Original descriptor type of data to be coerced    Desired descriptor type    Description    
  5428. typeChar    typeIntegertypeLongIntegertypeSMInttypeSMFloattypeShortIntegertypeFloattypeLongFloattypeShortFloattypeExtendedtypeComptypeMagnitude    Any string that is a valid representation of a number can be coerced into an equivalent numeric value.    
  5429.             
  5430.             
  5431.             
  5432.             
  5433.             
  5434.             
  5435. typeIntegertypeLongInteger typeSMInttypeSMFloattypeShortIntegertypeFloattypeLongFloattypeShortFloattypeExtendedtypeComptypeMagnitude    typeChar    Any numeric descriptor type can be coerced into the equivalent text string.    
  5436.             
  5437.             
  5438.             
  5439.             
  5440.             
  5441.             
  5442. typeIntegertypeLongInteger typeSMInttypeSMFloattypeShortInteger typeFloattypeLongFloattypeShortFloattypeExtendedtypeComptypeMagnitude    typeIntegertypeLongIntegertypeSMInttypeSMFloattypeShortIntegertypeFloattypeLongFloattypeShortFloattypeExtendedtypeComptypeMagnitude    Any numeric descriptor type can be coerced into any other numeric descriptor type.    
  5443.             
  5444.             
  5445.             
  5446.             
  5447.             
  5448.             
  5449. typeChar    typeTypetypeEnumeratedtypeKeyword
  5450. typeProperty    Any four-character string can be coerced to one of these descriptor types.    
  5451.             
  5452.             
  5453.             
  5454. typeEnumeratedtypeKeywordtypePropertytypeType    typeChar    Any of these descriptor types can be coerced to the equivalent text string.    
  5455.         
  5456. continued    
  5457. typeIntlText    typeChar    The result contains text only, without the script code or language code from the original descriptor record.    
  5458. typeTrue    typeBoolean    The result is the Boolean value TRUE.    
  5459. typeFalse    typeBoolean    The result is the Boolean value FALSE.    
  5460. typeEnumerated    typeBoolean    The enumerated value 'true' becomes the Boolean value TRUE. The enumerated value 'fals' becomes the Boolean value FALSE.    
  5461. typeBoolean    typeEnumerated    The Boolean value FALSE becomes the enumerated value 'fals'. The Boolean value TRUE becomes the enumerated value 'true'.    
  5462. typeShortInteger
  5463. typeSMInt    typeBoolean    A value of 1 becomes the Boolean value TRUE. A value of 0 becomes the Boolean value FALSE.    
  5464. typeBoolean    typeShortInteger typeSMInt    A value of FALSE becomes 0. A value of TRUE becomes 1.    
  5465. typeAlias    typeFSS    An alias record is coerced into a file system specification record.    
  5466. typeAppleEvent    typeAppParameters    An Apple event is coerced into a list of application parameters for the LaunchParamBlockRec parameter block.    
  5467. any descriptor type    typeAEList    A descriptor record is coerced into a descriptor list containing a single item.    
  5468. typeAEList    type of list item    A descriptor list containing a single descriptor record is coerced into a descriptor record.     
  5469.  
  5470. NOTESome of the descriptor types listed in this table are synonyms; for example, the constants typeSMInt and typeShortInteger have the same four-character code, 'shor'.
  5471.  
  5472.  
  5473. Interacting With the User
  5474.  
  5475. When your application receives an Apple event, it may need to interact with the user. For example, it may need to display a dialog box asking the user for additional information or confirmation. You must use the AEInteractWithUser function to make sure your application is in the foreground before it actually interacts with the user. 
  5476. Both the client application and the server application specify their preferences for user interaction. The AEInteractWithUser function checks the user interaction preferences set by each application. If both the client and the server allow user interaction, AEInteractWithUser usually posts a notification request, and the Notification Manager brings the server to the foreground after the user responds to the notification request. 
  5477. The AEInteractWithUser function can also bring the server application directly to the foreground, but only if the client application is the active application on the same computer and has set two flags in the sendMode parameter of the AESend function: the kAEWaitReply flag, which indicates that it is waiting for a reply, and the kAECanSwitchLayer flag, which indicates that it wants the server application to come directly to the foreground rather than posting a notification request.
  5478. To specify its preferences for how the server application should interact with the user, the client application sets various flags in the sendMode parameter to AESend. The Apple Event Manager sets the corresponding flags in the keyInteractLevelAttr attribute of the Apple event.
  5479. The server application sets its preferences with the AESetInteractionAllowed function. This function lets your application specify whether it allows interaction with the user as a result of receiving an Apple event from itself; from itself and other processes on the local computer; or from itself, local processes, and processes from another computer on the network.
  5480. Your application calls the AEInteractWithUser function before interacting with the user. If AEInteractWithUser returns the noErr result code, then your application is currently in the front and free to interact with the user. If AEInteractWithUser returns the errAENoUserInteraction result code, the conditions didn’t allow user interaction and your application should not interact with the user.
  5481. The rest of this section explains how to set user interactions for the client and server applications and the practical effect these settings have when a server needs to interact with a user.
  5482. Setting the Client Application’s User Interaction Preferences
  5483.  
  5484. The client application sets its user interaction preferences by setting flags in the sendMode parameter to the AESend function. The Apple Event Manager automatically adds the specified flags to the keyInteractLevelAttr attribute of the Apple event. These flags are represented by the following constants:
  5485. Flag    Description    
  5486. kAENeverInteract    The server application should never interact with the user in response to the Apple event. If this flag is set, AEInteractWithUser returns the errAENoUserInteraction result code. This flag is the default when an Apple event is sent to a remote application.    
  5487. kAECanInteract    The server application can interact with the user in response to the Apple event—by convention, if the user needs to supply information to the server. If this flag is set and the server allows interaction, AEInteractWithUser either brings the server application to the foreground or posts a notification request. This flag is the default when an Apple event is sent to a local application.     
  5488. kAEAlwaysInteract    The server application can interact with the user in response to the Apple event—by convention, whenever the server application normally asks a user to confirm a decision or interact in any other way, even if no additional information is needed from the user. If this flag is set and the server allows interaction, AEInteractWithUser either brings the server application to the foreground or posts a notification request.     
  5489.  
  5490. For example, suppose a client application sends a Set Data event to a database application to change a customer’s address. The database application is configured to request user confirmation of changes to a customer’s record. In this case the client sets the kAECanInteract flag before sending the event. Thus, the database application attempts to interact with the user if interaction is allowed. If interaction is not allowed, the database makes the correction anyway without consulting the user. However, if the client application sends a Delete event to delete a customer’s record entirely and sets the kAEAlwaysInteract flag, the database application deletes the specified record only if it can interact with the user first and receives confirmation of the decision to delete a record. If interaction with the user is not allowed, the database application returns an error. By setting the kAEAlwaysInteract flag, the client application ensures that the entire record won’t be lost if the user sends the Delete event by mistake.
  5491. If the client application doesn’t specify any of the three user interaction flags, the Apple Event Manager sets either the kAENeverInteract or the kAECanInteract flag in the keyInteractLevelAttr attribute of the Apple event, depending on the location of the server application. If the server application is on a remote computer, the Apple Event Manager sets the kAENeverInteract flag as the default. If the server application is on the local computer, the Apple Event Manager sets the kAECanInteract flag as the default.
  5492. In addition to the three user interaction flags, the client application can set another flag in the sendMode parameter to AESend to request that the Apple Event Manager immediately bring the server application directly to the foreground instead of posting a notification request:
  5493. Flag    Description    
  5494. kAECanSwitchLayer    If both the client and server allow interaction, and if the client application is the active application on the local computer and is waiting for a reply (that is, it has set the kAEWaitReply flag), AEInteractWithUser brings the server directly to the foreground. Otherwise, AEInteractWithUser uses the Notification Manager to request that the user bring the server application to the foreground.      
  5495.  
  5496. Note that although the kAECanSwitchLayer flag must be set for the Apple Event Manager to bring the server application directly to the foreground, setting it does not guarantee that the Apple Event Manager will bypass the notification request if user interaction is permitted. Another flag, the kAEWaitReply flag, must also be set in the sendMode parameter, and the client application must provide an idle function.
  5497. The kAEWaitReply flag is one of three flags in the sendMode parameter that a client application can set to specify whether and how the client should wait for a reply. (For a description of these flags, see “Sending an Apple Event and Handling the Reply” on page 3-30.) If the client application is not waiting for a reply, the user may have continued with other work. An application switch at this point might be unexpected and would thus violate the principle of user control as described in Macintosh Human Interface Guidelines.
  5498. If the client application sets the kAEWaitReply flag, it should also provide an idle function when it calls AESend so that it can handle events such as update events that it receives while waiting for the reply. Idle functions are described in “Writing an Idle Function,” which begins on page 5-21.
  5499. When a server application calls AEInteractWithUser, the function first checks whether the kAENeverInteract flag in the keyInteractLevelAttr attribute of the Apple event is set. (The Apple Event Manager sets this attribute according to the flags specified in the sendMode parameter of AESend.) If the kAENeverInteract flag is set, AEInteractWithUser immediately returns the errAENoUserInteraction result code. If the client specified kAECanInteract or kAEAlwaysInteract, AEInteractWithUser checks the server’s preferences for user interaction. 
  5500. Setting the Server Application’s User Interaction Preferences
  5501.  
  5502. The server sets its user interaction preferences by using the AESetInteractionAllowed function. This function specifies the conditions under which your application is willing to interact with the user.
  5503. myErr := AESetInteractionAllowed(level);
  5504. The level parameter is of type AEInteractAllowed. 
  5505. TYPE        AEInteractAllowed = (kAEInteractWithSelf, 
  5506.                                     kAEInteractWithLocal, 
  5507.                                     kAEInteractWithAll);
  5508. You can specify one of these values for the interaction level:
  5509. Flag    Description    
  5510. kAEInteractWithSelf    Your server application can interact with the user in response to an Apple event only when your application is also the client application—that is, only when your application is sending the Apple event to itself.    
  5511. kAEInteractWithLocal    Your server application can interact with the user in response to an Apple event only if the client application is on the same computer as your application. This is the default if the server application does not call the function AESetInteractionAllowed.    
  5512. kAEInteractWithAll    Your server application can interact with the user in response to an Apple event sent by any client application on any computer.    
  5513.  
  5514. If the server application does not set the user interaction level, AEInteractWithUser uses kAEInteractWithLocal as the value.
  5515. If the application sends itself an Apple event (that is, if the application is both the client and the server) without setting the kAENeverInteract flag, AEInteractWithUser always allows user interaction. If the client application is a process on the local computer and specifies kAECanInteract or kAEAlwaysInteract, and if the server has set the interaction level to kAEInteractWithLocal or kAEInteractWithAll, then AEInteractWithUser allows user interaction. If the client is a process on a remote computer on the network and specifies kAECanInteract or kAEAlwaysInteract, AEInteractWithUser allows user interaction only if the server specified the kAEInteractWithAll flag for the interaction level. In all other cases, AEInteractWithUser does not allow user interaction.  
  5516. Requesting User Interaction
  5517.  
  5518. If your server application needs to interact with the user for any reason, it must call the AEInteractWithUser function to make sure it is in the foreground before it actually interacts with the user. When AEInteractWithUser allows user interaction (based on the client’s and server’s preferences), AEInteractWithUser brings the server application to the foreground—either directly or after the user responds to a notification request—and then returns a noErr result code. If AEInteractWithUser brings the server to the foreground directly, the client returns to the foreground immediately after the server has finished interacting with the user. If AEInteractWithUser brings the server to the foreground after the user responds to a notification request, the server remains in the foreground after completing the user interaction.
  5519. The AEInteractWithUser function specifies how long your handler is willing to wait for a response from the user. For example, if the timeout value is 900 ticks (15 seconds) and the Apple Event Manager posts a notification request, the Notification Manager begins to display a blinking icon in the upper-right corner of the screen, then removes the notification request (and the blinking icon) if the user does not respond within 15 seconds. (The discussion that follows describes some restrictions on the icons that can be displayed in this situation.)
  5520. Note that the timeout value passed to the AEInteractWithUser function is separate from the timeout value passed to the AESend function, which specifies how long the client application is willing to wait for the reply or return receipt from the server application. If AEInteractWithUser does not receive a response from the user within the specified time, AEInteractWithUser returns errAETimeout. 
  5521. You may want to give the user a method of setting the interaction level. For example, some users may not want to be interrupted while background processing of an Apple event occurs, or they may not want to respond to dialog boxes when your application is handling Apple events sent from another computer.
  5522. Listing 4-14 illustrates the use of the AEInteractWithUser function. You call this function before your application displays a dialog box or otherwise interacts with the user when processing an Apple event. You specify a timeout value, a pointer to a Notification Manager record, and the address of an idle function as parameters to AEInteractWithUser.
  5523. Listing 4-14    Using the AEInteractWithUser function
  5524.  
  5525. myErr := AEInteractWithUser(kAEDefaultTimeout, gMyNotifyRecPtr, 
  5526.                                      @MyIdleFunction);
  5527. IF myErr <> noErr THEN
  5528.     {the attempt to interact failed; do any error handling}
  5529.     DoError(myErr)
  5530. ELSE
  5531.     {interact with the user by displaying a dialog box }
  5532.     { or by interacting in any other way that is necessary}
  5533.     DisplayMyDialogBox; 
  5534. You can set a timeout value, in ticks, in the first parameter to AEInteractWithUser. Use the kAEDefaultTimeout constant if you want the Apple Event Manager to use a default value for the timeout value. The Apple Event Manager uses a timeout value of about one minute if you specify this constant. You can also specify the kNoTimeOut constant if your application is willing to wait an indefinite amount of time for a response from the user. Usually you should provide a timeout value, so that your application can complete processing of the Apple event in a reasonable amount of time. 
  5535. If you specify NIL instead of a Notification Manager record in the second parameter of AEInteractWithUser, the Apple Event Manager looks for an application icon with the ID specified by the application’s bundle ('BNDL') resource and the application’s file reference ('FREF') resource. The Apple Event Manager first looks for an 'SICN' resource with the specified ID; if it can’t find an 'SICN' resource, it looks for the 'ICN#' resource and compresses the icon to fit in the menu bar. The Apple Event Manager won’t look for any members of an icon family other than the icon specified in the 'ICN#' resource.
  5536. If the application doesn’t have 'SICN' or 'ICN#' resources, or if it doesn’t have a file reference resource, the Apple Event Manager passes NIL to the Notification Manager, and no icon appears in the upper-right corner of the screen. Therefore, if you want to display any icon other than those of type 'SICN' or 'ICN#', you must specify a notification record as the second parameter to the AEInteractWithUser function. 
  5537. Note
  5538. If you want the Notification Manager to use a color icon when it posts a notification request, you should provide a Notification Manager record that specifies a 'cicn' resource.u
  5539. The AEInteractWithUser function posts a notification request only when user interaction is allowed and the kAECanSwitchLayer flag in the keyInteractLevelAttr attribute is not set.
  5540. The last parameter to AEInteractWithUser specifies an idle function provided by your application. Your idle function should handle any update events, null events, operating-system events, or activate events while your application is waiting to be brought to the front. See “Writing an Idle Function” on page 5-21 for more information. 
  5541. Figure 4-1 illustrates a situation in which a client application (a forms application) might request a service from a server application (a database application). To perform this service, the server application must interact with the user.
  5542. Figure 4-1    A document with a button that triggers a Get Data event
  5543.  
  5544. Figure 4-1 shows part of an electronic form used to enter information about an order received by telephone. If the customer has ordered from the company before, the user can quickly retrieve the customer’s address and telephone number by clicking the Retrieve Customer Info button. In response, the forms application sends a Get Data event to a database application (SurfDB) currently open on the same computer. The Get Data event sent by the forms application (the client application for the ensuing transaction) asks SurfDB (the server) to locate the customer’s name in a table of addresses and return the customer’s address. When the forms application receives the reply Apple event, it can add the address data to the appropriate fields in the order form.
  5545. If SurfDB, as the server application, locates more than one entry for the specified customer name, it needs to interact with the user to determine which data to return in the reply Apple event. To interact with the user, the server application must be in the foreground, so that it can display a dialog box like the one shown in Figure 4-2.
  5546. Figure 4-2    A server application displaying a dialog box that requests information from the user
  5547.  
  5548. Figure 4-3, Figure 4-4, and Figure 4-5 illustrate two methods of dealing with this situation. Figure 4-3 shows the behavior of the server application that is common to both methods. In both cases, the server uses AESetInteractionAllowed to set its own interaction level to kAEInteractWithLocal. After calling AEResolve to locate the requested data, the server application discovers that two addresses match the name the user typed into the electronic form. The server then calls AEInteractWithUser with a timeout value of kAEDefaultTimeout so it can find out which address the user wants. 
  5549. Figure 4-3    Handling user interaction
  5550.  
  5551. Figure 4-4 shows the circumstances in which the server application’s call to AEInteractWithUser shown in Figure 4-3 will cause the Apple Event Manager to bring the server application directly to the foreground. The client application sets the kAECanInteract, kAECanSwitchLayer, and kAEWaitReply flags in the sendMode parameter of the AESend function when it sends the Get Data event shown in the figure. These flags indicate that the client application expects the user to wait until the address appears in the appropriate fields of the electronic form before continuing with any other work. In this case, an automatic layer switch will not surprise the user and will avoid the additional user action required to respond to a notification request, so AEInteractWithUser brings the server application directly to the foreground and returns a noErr result code. The server application then displays the dialog box requesting that the user select the desired customer. 
  5552. After the user selects the desired customer and clicks OK, the server application’s Get Data event handler returns. The Apple Event Manager immediately brings the client application to the foreground, and the client application displays the requested customer information in the appropriate fields. 
  5553. Figure 4-4    Handling user interaction with the kAEWaitReply flag set
  5554.  
  5555. Figure 4-5 shows the circumstances in which the server application’s call to AEInteractWithUser in Figure 4-3 will cause the Apple Event Manager to post a notification request rather than bringing the server application directly to the foreground. 
  5556. Figure 4-5    Handling user interaction with the kAEQueueReply flag set  
  5557.  
  5558. The only difference between the Get Data event shown in Figure 4-4 and the Get Data event shown in Figure 4-5 is that the client application has set the kAEQueueReply flag instead of the kAEWaitReply flag in the sendMode parameter of AESend and has not set the kAECanSwitchLayer flag. This combination of flags indicates that the client application expects the user to continue filling in other parts of the form, such as the items being ordered; the address will just appear after a while, provided there is no duplicate name. In this case, an automatic layer switch would disrupt the user’s work. Instead of bringing the server application directly to the foreground, AEInteractWithUser uses the Notification Manager to post a notification request.
  5559. After the user has responded to the request and has brought the server application to the foreground, AEInteractWithUser returns a noErr result code, and the server application displays the dialog box requesting that the user select the desired customer. When the user selects a customer and clicks OK, the server application’s Get Data event handler returns. Because the user brought the server to the foreground manually, the server remains in the foreground after the handler returns. 
  5560.  
  5561. Reference to Responding to Apple Events
  5562.  
  5563. This section describes the basic Apple Event Manager data structures and routines that your application can use to respond to Apple events. It also describes the syntax for application-defined Apple event handlers and coercion handlers that your application can provide for use by the Apple Event Manager.
  5564. For information about routines used to create and send Apple events, see the chapter “Creating and Sending Apple Events” in this book. For information about routines and data structures used with object specifier records, see the chapter “Resolving and Creating Object Specifier Records” in this book.
  5565. Data Structures Used by the Apple Event Manager
  5566.  
  5567. This section summarizes the major data structures used by the Apple Event Manager. For an overview of the relationships among these data structures, see “Data Structures Within Apple Events,” which begins on page 3-12.
  5568. Descriptor Records and Related Data Structures
  5569.  
  5570. Descriptor records are the fundamental data structures from which Apple events are constructed. A descriptor record is a data structure of type AEDesc. 
  5571. TYPE AEDesc = 
  5572.     RECORD                                            {descriptor record}
  5573.         descriptorType:                        DescType;                {type of data being passed}
  5574.         dataHandle:                         Handle;                {handle to data being passed}
  5575.     END;
  5576. Field descriptions
  5577. descriptorType
  5578. A four-character string of type DescType that indicates the type of data being passed.
  5579. dataHandle    A handle to the data being passed.
  5580. The descriptor type is a structure of type DescType, which in turn is of data type ResType—that is, a four-character code. Constants, rather than these four-character codes, are usually used to refer to descriptor types. Table 4-2 lists the constants for the basic descriptor types used by the Apple Event Manager.
  5581. Table 4-2    Descriptor types used by the Apple Event Manager (excluding those used with object specifier records)(continued)
  5582. Descriptor type    Value    Description    
  5583. typeBoolean    'bool'    Boolean value    
  5584. typeChar    'TEXT'    Unterminated string    
  5585. typeLongInteger    'long'    32-bit integer    
  5586. typeInteger    'long'    32-bit integer    
  5587. typeShortInteger    'shor'    16-bit integer    
  5588. typeSMInt    'shor'    16-bit integer    
  5589. typeLongFloat    'doub'    SANE double    
  5590. typeFloat    'doub'    SANE double    
  5591. typeShortFloat    'sing'    SANE single    
  5592. typeSMFloat    'sing'    SANE single    
  5593. typeExtended    'exte'    SANE extended    
  5594. typeComp    'comp'    SANE comp    
  5595. typeMagnitude    'magn'    Unsigned 32-bit integer    
  5596. typeAEList    'list'    List of descriptor records    
  5597. typeAERecord    'reco'    List of keyword-specified descriptor records    
  5598. typeAppleEvent    'aevt'    Apple event record    
  5599. typeTrue    'true'    TRUE Boolean value    
  5600.         
  5601. continued    
  5602. typeFalse    'fals'    FALSE Boolean value    
  5603. typeAlias    'alis'    Alias record    
  5604. typeEnumerated    'enum'    Enumerated data    
  5605. typeType    'type'    Four-character code for event class or event ID    
  5606. typeAppParameters    'appa'    Process Manager launch parameters    
  5607. typeProperty    'prop'    Apple event property    
  5608. typeFSS    'fss '    File system specification    
  5609. typeKeyword    'keyw'    Apple event keyword    
  5610. typeSectionH    'sect'    Handle to a section record    
  5611. typeWildCard    '****'    Matches any type    
  5612. typeApplSignature    'sign'    Application signature    
  5613. typeSessionID    'ssid'    Session reference number    
  5614. typeTargetID    'targ'    Target ID record    
  5615. typeProcessSerialNumber    'psn '    Process serial number    
  5616. typeNull    'null'    Nonexistent data (data handle is NIL)     
  5617.  
  5618. For information about descriptor records and descriptor types used with object specifier records, see the chapter “Resolving and Creating Object Specifier Records” in this book. 
  5619. Apple event attributes, Apple event parameters, object specifier records, tokens, and most of the other data structures used by the Apple Event Manager are constructed from one or more descriptor records. The Apple Event Manager identifies the various parts of an Apple event by means of keywords associated with the corresponding descriptor records. The AEKeyword data type is defined as a four-character code.
  5620. TYPE        AEKeyword = PACKED ARRAY[1..4] OF Char;
  5621. Constants are typically used for keywords. A keyword combined with a descriptor record forms a keyword-specified descriptor record, which is defined by a data structure of type AEKeyDesc.
  5622. TYPE        AEKeyDesc = 
  5623.         RECORD
  5624.             descKey:                    AEKeyword;                    {keyword}
  5625.             descContent:                    AEDesc;                    {descriptor record}
  5626.         END;
  5627. Field descriptions
  5628. Field descriptions
  5629. descKey    A four-character code of type AEKeyword that identifies the data in the descContent field.
  5630. descContent    A descriptor record of type AEDesc.
  5631. Every Apple event includes an attribute that contains the address of the target application. A descriptor record that contains an application’s address is called an address descriptor record.
  5632. TYPE        AEAddressDesc = AEDesc;                                        {address descriptor record}
  5633. Many Apple Event Manager functions take or return lists of descriptor records in a special descriptor record called a descriptor list. A descriptor list is a structure of data type AEDescList whose data consists of a list of other descriptor records.
  5634. TYPE        AEDescList = AEDesc;                                        {list of descriptor records}
  5635. Other Apple Event Manager functions take or return lists of keyword-specified descriptor records in the form of an AE record. An AE record is a structure of data type AERecord whose data handle refers to a list of keyword-specified descriptor records.
  5636. TYPE        AERecord = AEDescList;                                        {list of keyword-specified }
  5637.                                                 { descriptor records}
  5638. The handle for a descriptor list of data type AERecord refers to a list of keyword-specified descriptor records that specify Apple event parameters; they cannot specify Apple event attributes.
  5639. Finally, a full-fledged Apple event, including both attributes and parameters, is an Apple event record, which is a structure of data type AppleEvent.
  5640. TYPE        AppleEvent = AERecord;                                        {list of attributes and     }
  5641.                                                 { parameters for an Apple }
  5642.                                                 { event}
  5643. The event class and event ID of an Apple event are specified in Apple Event Manager routines by structures of data types AEEventClass and AEEventID, respectively.
  5644. TYPE AEEventClass = PACKED ARRAY[1..4] OF Char;
  5645. TYPE AEEventID = PACKED ARRAY[1..4] OF Char;
  5646. For more information about descriptor records and the other data structures described in this section, see “Data Structures Within Apple Events,” which begins on page 3-12. 
  5647. With the exception of array data records, which are described in the next section, the other Apple Event Manager data structures used in responding to Apple events are described in “Routines for Responding to Apple Events,” beginning on page 4-61, under the descriptions of the routines that use them.
  5648. Apple Event Array Data Types
  5649.  
  5650. The AEGetArray function (see page 4-77) creates a Pascal or C array that corresponds to an Apple event array in a descriptor list, and the AEPutArray function (see page 5-31) adds data specified in a buffer to a descriptor list as an Apple event array. 
  5651. You can use the data type AEArrayType to define the type of Apple event array you want to add to or obtain from a descriptor list.
  5652. TYPE AEArrayType = (kAEDataArray, kAEPackedArray, kAEHandleArray,
  5653.                           kAEDescArray, kAEKeyDescArray);
  5654. When your application adds an Apple event array to a descriptor list, it provides the data for an Apple event array in an array data record, which is defined by the data type AEArrayData.
  5655. TYPE AEArrayData = 
  5656.     RECORD                                        {data for an Apple event array}
  5657.         CASE AEArrayType OF
  5658.         kAEDataArray:
  5659.             (AEDataArray:                         ARRAY[0..0] OF Integer);
  5660.         kAEPackedArray:
  5661.             (AEPackedArray:                         PACKED ARRAY[0..0] OF Char);
  5662.         kAEHandleArray:
  5663.             (AEHandleArray:                         ARRAY[0..0] OF Handle);
  5664.         kAEDescArray:
  5665.             (AEDescArray:                         ARRAY[0..0] OF AEDesc);
  5666.         kAEKeyDescArray:
  5667.             (AEKeyDescArray:                         ARRAY[0..0] OF AEKeyDesc);
  5668.     END;
  5669. The type of array depends on the data for the array:
  5670. Array type    Description of Apple event array    
  5671. kAEDataArray    Array items consist of data of the same size and same type, and are aligned on word boundaries.    
  5672. kAEPackedArray    Array items consist of data of the same size and same type, and are packed without regard for word boundaries.    
  5673. kAEHandleArray    Array items consist of handles to data of variable size and the same type.    
  5674. kAEDescArray    Array items consist of descriptor records of different descriptor types with data of variable size.    
  5675. kAEKeyDescArray    Array items consist of keyword-specified descriptor records with different keywords, different descriptor types, and data of variable size.    
  5676.  
  5677. Array items in Apple event arrays of type kAEDataArray, kAEPackedArray, or kAEHandleArray must be factored—that is, contained in a factored descriptor list. Before adding array items to a factored descriptor list, you should provide both a pointer to the data that is common to all array items and the size of that common data when you first call AECreateList to create a factored descriptor list. When you call AEPutArray to add the array data to such a descriptor list, the Apple Event Manager automatically isolates the common data you specified in the call to AECreateList.
  5678. When you call AEGetArray or AEPutArray, you specify a pointer of data type AEArrayDataPointer that points to a buffer containing the data for the array.
  5679. TYPE AEArrayDataPointer = ^AEArrayData; 
  5680. For more information about using AECreateList to create factored descriptor lists for arrays, see page 5-28. For information about using AEGetArray and AEPutArray, see page 4-77 and page 5-31, respectively.  
  5681. Routines for Responding to Apple Events
  5682.  
  5683. This section describes the Apple Event Manager routines you can use to create and manage the Apple event dispatch tables, dispatch Apple events, extract information from Apple events, request user interaction, request more time to respond to Apple events, suspend and resume Apple event handling, delete descriptor records, deallocate memory for descriptor records, create and manage the coercion handler and special handler dispatch tables, and get information about the Apple Event Manager.
  5684. Because the Apple Event Manager uses the services of the Event Manager, which in turn uses the services of the PPC Toolbox, the routines described in this section may return Event Manager and PPC Toolbox result codes in addition to the Apple Event Manager result codes listed.
  5685. Creating and Managing the Apple Event Dispatch Tables
  5686.  
  5687. An Apple event dispatch table contains entries that specify the event class and event ID that refer to one or more Apple events, the address of the handler routine that handles those Apple events, and a reference constant. You can use the AEInstallEventHandler function to add entries to the Apple event dispatch table. This function sets up the initial mapping between the handlers in your application and the Apple events that they handle.
  5688. To get the address of a handler currently in the Apple event dispatch table, use the AEGetEventHandler function. If you need to remove any of your Apple event handlers after the mapping between handlers and Apple events is established, you can use the AERemoveEventHandler function. 
  5689. AEInstallEventHandler
  5690.  
  5691. You can use the AEInstallEventHandler function to add an entry to either your application’s Apple event dispatch table or the system Apple event dispatch table.
  5692. FUNCTION AEInstallEventHandler (theAEEventClass: AEEventClass;
  5693.                                           theAEEventID: AEEventID; 
  5694.                                           handler: EventHandlerProcPtr; 
  5695.                                           handlerRefcon: LongInt;
  5696.                                           isSysHandler: Boolean): OSErr;
  5697. theAEEventClass
  5698. The event class for the Apple event or events to be dispatched for this entry. The AEEventClass data type is defined as a four-character code:
  5699.                 TYPE AEEventClass = PACKED ARRAY[1..4] OF Char;
  5700. theAEEventID
  5701. The event ID for the Apple event or events to be dispatched for this entry. The AEEventID data type is defined as a four-character code:
  5702.                 TYPE AEEventID = PACKED ARRAY[1..4] OF Char;
  5703. handler     A pointer to an Apple event handler for this dispatch table entry. Note that a handler in the system dispatch table must reside in the system heap; this means that if the value of the isSysHandler parameter is TRUE, the handler parameter should point to a location in the system heap. Otherwise, if you put your system handler code in your application heap, you must use AERemoveEventHandler to remove the handler before your application terminates.
  5704. handlerRefcon 
  5705. A reference constant that is passed by the Apple Event Manager to the handler each time the handler is called. If your handler doesn’t use a reference constant, use 0 as the value of this parameter. 
  5706. isSysHandler 
  5707. Specifies the dispatch table to which you want to add the handler. If the value of isSysHandler is TRUE, the Apple Event Manager adds the handler to the system Apple event dispatch table. Entries in the system dispatch table are available to all applications. If the value of isSysHandler is FALSE, the Apple Event Manager adds the handler to your application’s Apple event dispatch table. The application’s dispatch table is searched first; the system dispatch table is searched only if the necessary handler is not found in your application’s dispatch table.
  5708. DESCRIPTION
  5709. The AEInstallEventHandler function creates an entry in the Apple event dispatch table. You must supply parameters that specify the event class, the event ID, the address of the handler that handles Apple events of the specified event class and event ID, and whether the handler is to be added to the system Apple event dispatch table or your application’s Apple event dispatch table. You can also specify a reference constant that the Apple Event Manager passes to your handler whenever your handler processes an Apple event.
  5710. The parameters theAEEventClass and theAEEventID specify the event class and event ID of the Apple events to be handled by the handler for this dispatch table entry. For these parameters, you must provide one of the following combinations:
  5711. n    the event class and event ID of a single Apple event to be dispatched to the handler
  5712. n    the typeWildCard constant for theAEEventClass and an event ID for theAEEventID, which indicate that Apple events from all event classes whose event IDs match theAEEventID should be dispatched to the handler
  5713. n    an event class for theAEEventClass and the typeWildCard constant for theAEEventID, which indicate that all events from the specified event class should be dispatched to the handler
  5714. n    the typeWildCard constant for both the theAEEventClass and theAEEventID parameters, which indicates that all Apple events should be dispatched to the handler 
  5715. IMPORTANT
  5716. If you use the typeWildCard constant for either the theAEEventClass or the theAEEventID parameter (or for both parameters), the corresponding handler must return the error errAEEventNotHandled if it does not handle a particular event.s
  5717. If there was already an entry in the specified dispatch table for the same event class and event ID, it is replaced. Therefore, before installing a handler for a particular Apple event in the system dispatch table, use the AEGetEventHandler function (described next) to determine whether the table already contains a handler for that event. If an entry exists, AEGetEventHandler returns a reference constant and a pointer to that event handler. Chain the existing handler to your handler by providing pointers to the previous handler and its reference constant in the handlerRefcon parameter of AEInstallEventHandler. When your handler is done, use these pointers to call the previous handler. If you remove your system Apple event handler, be sure to reinstall the chained handler. 
  5718. SPECIAL CONSIDERATIONS
  5719. Before an application calls a system Apple event handler, system software has set up the A5 register for the calling application. For this reason, if you provide a system Apple event handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.
  5720. RESULT CODESnoErr    0    No error    
  5721. paramErr    –50    Parameter error (handler pointer is NIL or odd)    
  5722. memFullErr    –108    Not enough room in heap zone    
  5723.  
  5724. SEE ALSO
  5725. For more information about installing Apple event handlers, see “Installing Entries in the Apple Event Dispatch Tables,” which begins on page 4-7.
  5726. AEGetEventHandler
  5727.  
  5728. You can use the AEGetEventHandler function to get an entry from an Apple event dispatch table.
  5729. FUNCTION AEGetEventHandler (theAEEventClass: AEEventClass; 
  5730.                                      theAEEventID: AEEventID; 
  5731.                                      VAR handler: EventHandlerProcPtr; 
  5732.                                         VAR handlerRefcon: LongInt; 
  5733.                                      isSysHandler: Boolean): OSErr;
  5734. theAEEventClass
  5735. The value of the event class field of the dispatch table entry for the desired handler.
  5736. theAEEventID
  5737. The value of the event ID field of the dispatch table entry for the desired handler.
  5738. handler    The AEGetEventHandler function returns, in this parameter, a pointer to the specified handler.
  5739. handlerRefcon
  5740. The AEGetEventHandler function returns, in this parameter, the reference constant from the dispatch table entry for the specified handler.
  5741. isSysHandler 
  5742. Specifies the Apple event dispatch table from which to get the handler. If the value of isSysHandler is TRUE, the AEGetEventHandler function returns the handler from the system dispatch table. If the value is FALSE, AEGetEventHandler returns the handler from your application’s dispatch table.
  5743. DESCRIPTION
  5744. The AEGetEventHandler function returns, in the handler parameter, a pointer to the handler for the Apple event dispatch table entry you specify in the parameters theAEEventClass and theAEEventID. You can use the typeWildCard constant for either or both of these parameters; however, AEGetEventHandler returns an error unless an entry exists that specifies typeWildCard in exactly the same way. For example, if you specify typeWildCard in both the theAEEventClass parameter and the theAEEventID parameter, the Apple Event Manager will not return the first handler for any event class and event ID in the dispatch table; instead, the dispatch table must contain an entry that specifies type typeWildCard for both the event class and the event ID. 
  5745. RESULT CODESnoErr    0    No error    
  5746. errAEHandlerNotFound    –1717    No handler found for an Apple event    
  5747.  
  5748. SEE ALSO
  5749. For an explanation of wildcard values, see the description of the AEInstallEventHandler function on page 4-62.
  5750. AERemoveEventHandler
  5751.  
  5752. You can use the AERemoveEventHandler function to remove an entry from an Apple event dispatch table.
  5753. FUNCTION AERemoveEventHandler (theAEEventClass: AEEventClass; 
  5754.                                          theAEEventID: AEEventID; 
  5755.                                          handler: EventHandlerProcPtr; 
  5756.                                          isSysHandler: Boolean): OSErr;
  5757. theAEEventClass
  5758. The event class for the handler whose entry you want to remove from the dispatch table.
  5759. theAEEventID
  5760. The event ID for the handler whose entry you want to remove from the Apple event dispatch table.
  5761. handler    A pointer to the handler to be removed. Although the parameters theAEEventClass and theAEEventID would be sufficient to identify the handler to be removed, providing the handler parameter is a recommended safeguard that ensures that you remove the correct handler. If the value of this parameter is NIL, the Apple Event Manager relies solely on the event class and event ID to identify the handler to be removed.
  5762. isSysHandler 
  5763. Specifies the dispatch table from which to remove the handler. If the value of isSysHandler is TRUE, AERemoveEventHandler removes the handler from the system dispatch table. If the value is FALSE, AERemoveEventHandler removes the handler from your application’s dispatch table.
  5764. DESCRIPTION
  5765. The AERemoveEventHandler function removes the Apple event dispatch table entry you specify in the parameters theAEEventClass, theAEEventID, and handler. You can use the typeWildCard constant for the theAEEventClass or the theAEEventID parameter, or for both parameters; however, AERemoveEventHandler returns an error unless an entry exists that specifies typeWildCard in exactly the same way. For example, if you specify typeWildCard in both the theAEEventClass parameter and the theAEEventID parameter, the Apple Event Manager will not remove the first handler for any event class and event ID in the dispatch table; instead, the dispatch table must contain an entry that specifies type typeWildCard for both the event class and the event ID. 
  5766. RESULT CODESnoErr    0    No error    
  5767. errAEHandlerNotFound    –1717    No handler found for an Apple event    
  5768.  
  5769. SEE ALSO
  5770. For an explanation of wildcard values, see the description of the AEInstallEventHandler function on page 4-62.
  5771. Dispatching Apple Events
  5772.  
  5773. After receiving a high-level event (and optionally determining whether it is a type of high-level event other than an Apple event that your application might support), your application typically calls the AEProcessAppleEvent function to determine the type of Apple event received and call the corresponding handler.
  5774. AEProcessAppleEvent
  5775.  
  5776. You can use the AEProcessAppleEvent function to call the appropriate handler for a specified Apple event.  
  5777. FUNCTION AEProcessAppleEvent 
  5778.                                 (theEventRecord: EventRecord): OSErr;
  5779. theEventRecord
  5780. The event record for the Apple event.
  5781. DESCRIPTION
  5782. The AEProcessAppleEvent function looks first in the application’s special handler dispatch table for an entry that was installed with the constant keyPreDispatch. If the application’s special handler dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the function looks in the application’s Apple event dispatch table for an entry that matches the event class and event ID of the specified Apple event. 
  5783. If the application’s Apple event dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the AEProcessAppleEvent function looks in the system special handler dispatch table for an entry that was installed with the constant keyPreDispatch. If the system special handler dispatch table does not include such a handler or if the handler returns errAEEventNotHandled, the function looks in the system Apple event dispatch table for an entry that matches the event class and event ID of the specified Apple event. 
  5784. If the system Apple event dispatch table does not include such a handler, the Apple Event Manager returns the result code errAEEventNotHandled to the server application and, if the client application is waiting for a reply, to the client application.
  5785. If AEProcessAppleEvent finds an entry in one of the dispatch tables that matches the event class and event ID of the specified Apple event, it calls the corresponding handler.
  5786. SPECIAL CONSIDERATIONS
  5787. If an Apple event dispatch table contains one entry for an event class and a specific event ID, and also contains another entry that is identical except that it specifies a wildcard value for either the event class or the event ID, the Apple Event Manager dispatches the more specific entry. For example, if an Apple event dispatch table includes one entry that specifies the event class as kAECoreSuite and the event ID as kAEDelete, and another entry that specifies the event class as kAECoreSuite and the event ID as typeWildCard, the Apple Event Manager dispatches the Apple event handler associated with the entry that specifies the event ID as kAEDelete.
  5788. RESULT CODESnoErr    0    No error    
  5789. memFullErr    –108    Not enough room in heap zone    
  5790. bufferIsSmall    –607    Buffer is too small    
  5791. noOutstandingHLE    –608    No outstanding high-level event    
  5792. errAECorruptData    –1702    Data in an Apple event could not be read    
  5793. errAENewerVersion    –1706    Need a newer version of the Apple Event Manager    
  5794. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event handler     
  5795.  
  5796. SEE ALSO
  5797. For an example of the use of AEProcessAppleEvent, see Listing 4-2 on page 4-6. 
  5798. For a description of an Apple event handler, see page 4-105. 
  5799. For more information about event processing, see the chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials.   
  5800. Getting Data or Descriptor Records Out of Apple Event Parameters and Attributes
  5801.  
  5802. The Apple Event Manager provides four functions that allow you to get data from Apple event parameters and attributes. The AEGetParamPtr and AEGetParamDesc functions get data from a specified Apple event parameter. The AEGetAttributePtr and AEGetAttributeDesc functions get data from a specified Apple event attribute. 
  5803. AEGetParamPtr
  5804.  
  5805. You can use the AEGetParamPtr function to get a pointer to a buffer that contains the data from a specified Apple event parameter.
  5806. FUNCTION AEGetParamPtr (theAppleEvent: AppleEvent; 
  5807.                                     theAEKeyword: AEKeyword;
  5808.                                 desiredType: DescType; 
  5809.                                 VAR typeCode: DescType; dataPtr: Ptr; 
  5810.                                 maximumSize: Size; 
  5811.                                 VAR actualSize: Size): OSErr;
  5812. theAppleEvent
  5813. The Apple event containing the desired parameter.
  5814. theAEKeyword 
  5815. The keyword that specifies the desired parameter.
  5816. desiredType
  5817. The desired descriptor type for the data to be returned; if the requested Apple event parameter is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType 
  5818. is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event parameter. 
  5819. typeCode     The descriptor type of the returned data.
  5820. dataPtr     A pointer to the buffer in which the returned data is stored.
  5821. maximumSize 
  5822. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter. 
  5823. actualSize
  5824. The length, in bytes, of the data for the specified Apple event parameter. If this value is larger than the value of the maximumSize parameter, not all of the data for the parameter was returned.
  5825. DESCRIPTION
  5826. The AEGetParamPtr function uses a buffer to return the data from a specified Apple event parameter, which it attempts to coerce to the descriptor type specified by the desiredType parameter. 
  5827. RESULT CODESnoErr    0    No error    
  5828. memFullErr    –108    Not enough room in heap zone    
  5829. errAECoercionFail     –1700    Data could not be coerced to the requested descriptor type    
  5830. errAEDescNotFound     –1701    Descriptor record was not found    
  5831. errAEWrongDataType    –1703    Wrong descriptor type    
  5832. errAENotAEDesc    –1704    Not a valid descriptor record    
  5833. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  5834.  
  5835. SEE ALSO
  5836. For examples of the use of AEGetParamPtr, see “Getting Data Out of an Apple Event,” which begins on page 4-25.
  5837. AEGetParamDesc
  5838.  
  5839. You can use the AEGetParamDesc function to get the descriptor record for a specified Apple event parameter.  
  5840. FUNCTION AEGetParamDesc (theAppleEvent: AppleEvent; 
  5841.                                  theAEKeyword: AEKeyword; 
  5842.                                  desiredType: DescType; 
  5843.                                  VAR result: AEDesc): OSErr;
  5844. theAppleEvent
  5845. The Apple event containing the desired parameter.
  5846. theAEKeyword 
  5847. The keyword that specifies the desired parameter.
  5848. desiredType 
  5849. The desired descriptor type for the descriptor record to be returned; if the requested Apple event parameter is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event parameter. 
  5850. result     The descriptor record from the desired Apple event parameter coerced to the descriptor type specified in desiredType.
  5851. DESCRIPTION
  5852. The AEGetParamDesc function returns, in the result parameter, the descriptor record for a specified Apple event parameter, which it attempts to coerce to the descriptor type specified by the desiredType parameter. Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it.
  5853. If AEGetParamDesc returns a nonzero result code, it returns a null descriptor record unless the Apple Event Manager is not available because of limited memory.
  5854. RESULT CODESnoErr    0    No error    
  5855. memFullErr    –108    Not enough room in heap zone    
  5856. errAECoercionFail     –1700    Data could not be coerced to the requested descriptor type    
  5857. errAEDescNotFound     –1701    Descriptor record was not found    
  5858. errAENotAEDesc    –1704    Not a valid descriptor record    
  5859. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  5860.  
  5861. SEE ALSO
  5862. For an example of the use of AEGetParamDesc, see “Getting Data Out of an Apple Event Parameter,” which begins on page 4-26.   
  5863. AEGetAttributePtr
  5864.  
  5865. You can use the AEGetAttributePtr function to get a pointer to a buffer that contains the data from a specified Apple event attribute.
  5866. FUNCTION AEGetAttributePtr (theAppleEvent: AppleEvent; 
  5867.                                      theAEKeyword: AEKeyword; 
  5868.                                      desiredType: DescType; 
  5869.                                         VAR typeCode: DescType; dataPtr: Ptr; 
  5870.                                         maximumSize: Size; 
  5871.                                      VAR actualSize: Size): OSErr;
  5872. theAppleEvent
  5873. The Apple event containing the desired attribute.
  5874. theAEKeyword
  5875. The keyword that specifies the desired attribute.
  5876.     TYPE AEKeyword = PACKED ARRAY[1..4] OF Char;
  5877.     The keyword can be any of the constants listed in the description that follows.
  5878. desiredType
  5879. The desired descriptor type for the data to be returned; if the requested Apple event attribute is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event attribute. 
  5880. typeCode    The descriptor type of the returned data.
  5881. dataPtr     A pointer to the buffer in which the returned data is stored.
  5882. maximumSize 
  5883. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter. 
  5884. actualSize
  5885. The length, in bytes, of the data for the specified Apple event attribute. If this value is larger than the value of the maximumSize parameter, not all of the data for the attribute was returned.
  5886. DESCRIPTION
  5887. The AEGetAttributePtr function uses a buffer to return the data from an Apple event attribute with the specified keyword, which it attempts to coerce to the descriptor type specified by the desiredType parameter. You can specify the parameter theAEKeyWord using any of these constants:
  5888. CONST
  5889.     keyAddressAttr                                 = 'addr'; {address of target or }
  5890.                                                  { client application}
  5891.     keyEventClassAttr                                 = 'evcl'; {event class}
  5892.     keyEventIDAttr                                = 'evid'; {event ID}
  5893.     keyEventSourceAttr                                = 'esrc'; {nature of source }
  5894.                                                  { application}
  5895.     keyInteractLevelAttr                                = 'inte'; {settings to allow the }
  5896.                                                  { Apple Event Manager to }
  5897.                                                  { bring server application }
  5898.                                                  { to the foreground}
  5899.     keyMissedKeywordAttr                                = 'miss'; {first required parameter }
  5900.                                                  { remaining in Apple event}
  5901.     keyOptionalKeywordAttr                                = 'optk'; {list of optional }
  5902.                                                  { parameters for Apple }
  5903.                                                  { event}
  5904.     keyOriginalAddressAttr                                = 'from';             {address of original source }
  5905.                                                  { of Apple event; available }
  5906.                                                  { beginning with version }
  5907.                                                  { 1.01 of Apple Event }
  5908.                                                  { Manager}     
  5909.     keyReturnIDAttr                                 = 'rtid'; {return ID for reply Apple }
  5910.                                                  { event}
  5911.     keyTimeoutAttr                                = 'timo'; {length of time in ticks }
  5912.                                                  { that client will wait }
  5913.                                                  { for reply or result from } 
  5914.                                                  { the server}
  5915.     keyTransactionIDAttr                                = 'tran'; {transaction ID identifying }
  5916.                                                  { a series of Apple events}
  5917. RESULT CODESnoErr    0    No error    
  5918. memFullErr    –108    Not enough room in heap zone    
  5919. errAECoercionFail     –1700    Data could not be coerced to the requested descriptor type    
  5920. errAEDescNotFound     –1701    Descriptor record was not found    
  5921. errAENotAEDesc    –1704    Not a valid descriptor record    
  5922. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  5923.  
  5924. SEE ALSO
  5925. For an example of the use of the AEGetAttributePtr function, see “Getting Data Out of an Attribute” and “Writing Apple Event Handlers,” which begin on page 4-28 and page 4-33, respectively.
  5926. AEGetAttributeDesc
  5927.  
  5928. You can use the AEGetAttributeDesc function to get the descriptor record for a specified Apple event attribute.   
  5929. FUNCTION AEGetAttributeDesc (theAppleEvent: AppleEvent; 
  5930.                                       theAEKeyword: AEKeyword; 
  5931.                                       desiredType: DescType; 
  5932.                                           VAR result: AEDesc): OSErr;
  5933. theAppleEvent
  5934. The Apple event containing the desired attribute.
  5935. theAEKeyword 
  5936. The keyword that specifies the desired attribute.
  5937.     TYPE AEKeyword = PACKED ARRAY[1..4] OF Char;
  5938.     The keyword can be any of the constants listed in the description of AEGetAttributePtr on page 4-71.
  5939. desiredType
  5940. The desired descriptor type for the descriptor record to be returned; if the requested Apple event attribute is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned data is the same as the descriptor type of the Apple event attribute. 
  5941. result     A copy of the descriptor record from the desired attribute coerced to the descriptor type specified by the desiredType parameter.
  5942. DESCRIPTION
  5943. The AEGetAttributeDesc function returns, in the result parameter, the descriptor record for the Apple event attribute with the specified keyword. Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it.
  5944. If AEGetAttributeDesc returns a nonzero result code, it returns a null descriptor record unless the Apple Event Manager is not available because of limited memory. 
  5945. RESULT CODESnoErr    0    No error    
  5946. memFullErr    –108    Not enough room in heap zone    
  5947. errAECoercionFail    –1700    Data could not be coerced to the requested descriptor type    
  5948. errAEDescNotFound    –1701    Descriptor record was not found    
  5949. errAENotAEDesc    –1704    Not a valid descriptor record    
  5950. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  5951.  
  5952. Counting the Items in Descriptor Lists
  5953.  
  5954. The AECountItems function counts the number of descriptor records in any descriptor list, including an Apple event record.
  5955. AECountItems
  5956.  
  5957. You can use the AECountItems function to count the number of descriptor records in any descriptor list.
  5958. FUNCTION AECountItems (theAEDescList: AEDescList; 
  5959.                               VAR theCount: LongInt): OSErr;
  5960. theAEDescList
  5961. The descriptor list to be counted.
  5962. theCount    The AECountItems function returns the number of descriptor records in the specified descriptor list in this parameter.
  5963. RESULT CODESnoErr    0    No error    
  5964. errAENotAEDesc    –1704    Not a valid descriptor record     
  5965.  
  5966. SEE ALSO
  5967. For an example of the use of AECountItems, see “Getting Data Out of a Descriptor List,” which begins on page 4-31.
  5968. Getting Items From Descriptor Lists
  5969.  
  5970. The Apple Event Manager provides three functions that allow you to get items from any descriptor list, including an Apple event record. The AEGetNthPtr and AEGetNthDesc functions give you access to the data in a descriptor list. The AEGetArray function gets data from an array contained in a descriptor list.
  5971. AEGetNthPtr
  5972.  
  5973. You can use the AEGetNthPtr function to get a pointer to a buffer that contains a copy of a descriptor record from any descriptor list.
  5974. FUNCTION AEGetNthPtr (theAEDescList: AEDescList; index: LongInt; 
  5975.                              desiredType: DescType; 
  5976.                              VAR theAEKeyword: AEKeyword; 
  5977.                              VAR typeCode: DescType; dataPtr: Ptr; 
  5978.                              maximumSize: Size; 
  5979.                              VAR actualSize: Size): OSErr;
  5980. theAEDescList
  5981. The descriptor list containing the desired descriptor record.
  5982. index    The position of the desired descriptor record in the list (for example, 2 specifies the second descriptor record).
  5983. desiredType
  5984. The desired descriptor type for the copy of the descriptor record to be returned; if the desired descriptor record is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the copied descriptor record is the same as the descriptor type of the original descriptor record.
  5985. theAEKeyword
  5986. The keyword of the specified descriptor record, if you are getting data from a list of keyword-specified descriptor records; otherwise, AEGetNthPtr returns the value typeWildCard. 
  5987. typeCode    The descriptor type of the returned descriptor record.
  5988. dataPtr     A pointer to the buffer in which the returned descriptor record is stored.
  5989. maximumSize
  5990. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter.
  5991. actualSize
  5992. The length, in bytes, of the data for the specified descriptor record. If this value is larger than the value of the maximumSize parameter, not all of the data for the descriptor record was returned.
  5993. DESCRIPTION
  5994. The AEGetNthPtr function uses a buffer to return a specified descriptor record from a specified descriptor list; the function attempts to coerce the descriptor record to the descriptor type specified by the desiredType parameter.
  5995. RESULT CODESnoErr    0    No error    
  5996. memFullErr    –108    Not enough room in heap zone    
  5997. errAECoercionFail     –1700    Data could not be coerced to the requested descriptor type    
  5998. errAEDescNotFound     –1701    Descriptor record was not found    
  5999. errAEWrongDataType    –1703    Wrong descriptor type    
  6000. errAENotAEDesc    –1704    Not a valid descriptor record    
  6001. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  6002.  
  6003. SEE ALSO
  6004. For an example of the use of AEGetNthPtr, see Listing 4-10 on page 4-33.
  6005. AEGetNthDesc
  6006.  
  6007. You can use the AEGetNthDesc function to get a copy of a descriptor record from any descriptor list. 
  6008. FUNCTION AEGetNthDesc (theAEDescList: AEDescList; index: LongInt; 
  6009.                               desiredType: DescType; 
  6010.                               VAR theAEKeyword: AEKeyword; 
  6011.                               VAR result: AEDesc): OSErr;
  6012. theAEDescList 
  6013. The descriptor list containing the desired descriptor record.
  6014. index     The position of the desired descriptor record in the list (for example, 2 specifies the second descriptor record).
  6015. desiredType 
  6016. The desired descriptor type for the copy of the descriptor record to be returned; if the desired descriptor record is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the copied descriptor record is the same as the descriptor type of the original descriptor record.
  6017. theAEKeyword
  6018. The keyword of the specified descriptor record, if you are getting data from a list of keyword-specified descriptor records; otherwise, AEGetNthDesc returns the value typeWildCard. 
  6019. result    A copy of the desired descriptor record coerced to the descriptor type specified by the desiredType parameter.
  6020. DESCRIPTION
  6021. The AEGetNthDesc function returns a specified descriptor record from a specified descriptor list.Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it.
  6022. If AEGetNthDesc returns a nonzero result code, it returns a descriptor record of descriptor type typeNull. A descriptor record of this type does not contain any data.
  6023. RESULT CODESnoErr    0    No error    
  6024. memFullErr    –108    Not enough room in heap zone    
  6025. errAECoercionFail     –1700    Data could not be coerced to the requested descriptor type    
  6026. errAEDescNotFound     –1701    Descriptor record was not found    
  6027. errAENotAEDesc    –1704    Not a valid descriptor record    
  6028. errAEReplyNotArrived    –1718    Reply has not yet arrived     
  6029.  
  6030. AEGetArray
  6031.  
  6032. You can use the AEGetArray function to convert an Apple event array (an array created with the AEPutArray function and stored in a descriptor list) to the corresponding Pascal or C array and place the converted array in a buffer for which you have provided a pointer.
  6033. FUNCTION AEGetArray (theAEDescList: AEDescList; 
  6034.                             arrayType: AEArrayType; 
  6035.                             arrayPtr: AEArrayDataPointer; 
  6036.                             maximumSize: Size; 
  6037.                             VAR itemType: DescType; VAR itemSize: Size; 
  6038.                             VAR itemCount: LongInt): OSErr;
  6039. theAEDescList 
  6040. A descriptor list containing the desired array. If the array is of type kAEDataArray, kAEPackedArray, or kAEHandleArray, the descriptor list must be factored. 
  6041. arrayType     The Apple event array type to be converted. This is specified by one of the following constants: kAEDataArray, kAEPackedArray, kAEHandleArray, kAEDescArray, or kAEKeyDescArray.
  6042. arrayPtr     A pointer to the buffer for storing the array.
  6043. maximumSize 
  6044. The maximum length, in bytes, of the buffer for storing the array.
  6045. itemType    For arrays of type kAEDataArray, kAEPackedArray, or kAEHandleArray, the AEGetArray function returns the descriptor type of the returned array items in this parameter. 
  6046. itemSize    For arrays of type kAEDataArray or kAEPackedArray, the AEGetArray function returns the size (in bytes) of the returned array items in this parameter.
  6047. itemCount     The AEGetArray function returns the number of items in the resulting array in this parameter.
  6048. DESCRIPTION
  6049. The AEGetArray function uses a buffer identified by the pointer in the arrayPtr parameter to return the converted data for the Apple event array specified by the theAEDescList parameter. Even if the descriptor list that contains the array is factored, the converted data for each array item includes the data common to all the descriptor records in the list. The Apple Event Manager automatically reconstructs the common data for each item when you call AEGetArray.
  6050. RESULT CODESnoErr    0    No error    
  6051. memFullErr    –108    Not enough room in heap zone    
  6052. errAEWrongDataType    –1703    Wrong descriptor type    
  6053. errAENotAEDesc    –1704    Not a valid descriptor record    
  6054. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  6055.  
  6056. SEE ALSO
  6057. For more information about data types and constants used with AEGetArray, see “Apple Event Array Data Types” on page 4-60.
  6058. For information about creating and factoring descriptor lists for Apple event arrays, see the description of AECreateList on page 5-28. For information about adding an Apple event array to a descriptor list, see the description of AEPutArray on page 5-31.
  6059. Getting Data and Keyword-Specified Descriptor Records Out of AE Records
  6060.  
  6061. The Apple Event Manager provides two functions, AEGetKeyPtr and AEGetKeyDesc, that allow you to get data and descriptor records out of an AE record or an Apple event record.
  6062. AEGetKeyPtr
  6063.  
  6064. You can use the AEGetKeyPtr function to get a pointer to a buffer that contains the data from a keyword-specified descriptor record. You can use this function to get data from an AE record or an Apple event record.
  6065. FUNCTION AEGetKeyPtr (theAERecord: AERecord; 
  6066.                              theAEKeyword: AEKeyword; 
  6067.                              desiredType: DescType; 
  6068.                              VAR typeCode: DescType; 
  6069.                              dataPtr: Ptr; maximumSize: Size; 
  6070.                              VAR actualSize: Size): OSErr;
  6071. theAERecord 
  6072. The AE record containing the desired data.
  6073. theAEKeyword
  6074. The keyword that specifies the desired descriptor record.
  6075. desiredType
  6076. The desired descriptor type for the data to be returned; if the requested data is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of returned data is the same as the descriptor type of the original data. 
  6077. typeCode    The descriptor type of the returned data.
  6078. dataPtr     A pointer to the buffer for storing the data.
  6079. maximumSize 
  6080. The maximum length, in bytes, of the data to be returned. You must allocate at least this amount of storage for the buffer specified by the dataPtr parameter.
  6081. actualSize
  6082. The length, in bytes, of the data for the keyword-specified descriptor record. If this value is larger than the value of the maximumSize parameter, not all of the data for the parameter was returned.
  6083. DESCRIPTION
  6084. The AEGetKeyPtr function uses a buffer to return the data from a keyword-specified Apple event parameter, which the function attempts to coerce to the descriptor type specified by the desiredType parameter. 
  6085. RESULT CODESnoErr    0    No error    
  6086. memFullErr    –108    Not enough room in heap zone    
  6087. errAECoercionFail     –1700    Data could not be coerced to the requested descriptor type    
  6088. errAEDescNotFound     –1701    Descriptor record was not found    
  6089. errAEWrongDataType    –1703    Wrong descriptor type    
  6090. errAENotAEDesc    –1704    Not a valid descriptor record    
  6091. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  6092.  
  6093. AEGetKeyDesc
  6094.  
  6095. You can use the AEGetKeyDesc function to get the descriptor record for a keyword-specified descriptor record. You can use this function to get a descriptor record out of an AE record or an Apple event record.
  6096. FUNCTION AEGetKeyDesc (theAERecord: AERecord; 
  6097.                               theAEKeyword: AEKeyword; 
  6098.                                  desiredType: DescType; 
  6099.                               VAR result: AEDesc): OSErr;
  6100. theAERecord 
  6101. The AE record containing the desired descriptor record.
  6102. theAEKeyword
  6103. The keyword that specifies the desired descriptor record.
  6104. desiredType
  6105. The desired descriptor type for the descriptor record to be returned; if the requested descriptor record is not of this type, the Apple Event Manager attempts to coerce it to this type. If the value of desiredType is typeWildCard, no coercion is performed, and the descriptor type of the returned descriptor record is the same as the descriptor type of the original descriptor record.
  6106. result    A copy of the keyword-specified descriptor record, coerced to the descriptor type specified in the desiredType parameter. 
  6107. DESCRIPTION
  6108. The AEGetKeyDesc function returns a copy of the descriptor record for a keyword-specified descriptor record. Your application should call the AEDisposeDesc function to dispose of the resulting descriptor record after your application has finished using it. 
  6109. If AEGetKeyDesc returns a nonzero result code, it returns a descriptor record of descriptor type typeNull. A descriptor record of this type does not contain any data.
  6110. RESULT CODESnoErr    0    No error    
  6111. memFullErr    –108    Not enough room in heap zone    
  6112. errAECoercionFail    –1700    Data could not be coerced to the requested descriptor type    
  6113. errAEDescNotFound    –1701    Descriptor record was not found    
  6114. errAENotAEDesc    –1704    Not a valid descriptor record    
  6115. errAEReplyNotArrived    –1718    Reply has not yet arrived     
  6116.  
  6117. Requesting User Interaction
  6118.  
  6119. The Apple Event Manager provides three functions that allow you to set or request user interaction levels and to initiate user interaction when your application is the server application. The AESetInteractionAllowed and AEGetInteractionAllowed functions specify and return, respectively, the current user interaction preferences. Your application should call the AEInteractWithUser function before actually interacting with the user in response to an Apple event. 
  6120. AESetInteractionAllowed
  6121.  
  6122. You can use the AESetInteractionAllowed function to specify your application’s user interaction preferences for responding to an Apple event.
  6123. FUNCTION AESetInteractionAllowed 
  6124.                                         (level: AEInteractAllowed): OSErr;
  6125. level    The user interaction level to be set.
  6126. DESCRIPTION
  6127. The AESetInteractionAllowed function sets the user interaction level for a server application’s response to an Apple event. The level parameter must be one of three flags: kAEInteractWithSelf, kAEInteractWithLocal, or kAEInteractWithAll. 
  6128. Specifying the kAEInteractWithSelf flag allows the server application to interact with the user in response to an Apple event only when the client application and server application are the same—that is, only when the application is sending the Apple event to itself.
  6129. Specifying the kAEInteractWithLocal flag allows the server application to interact with the user in response to an Apple event only if the client application is on the same computer as the server application; this is the default if the AESetInteractionAllowed function is not used.
  6130. Specifying the kAEInteractWithAll flag allows the server application to interact with the user in response to an Apple event sent from any client application on any computer.
  6131. RESULT CODEnoErr    0    No error    
  6132.  
  6133. SEE ALSO
  6134. For more information about setting user preferences for a server application, see “Setting the Server Application’s User Interaction Preferences” on page 4-48.
  6135. AEGetInteractionAllowed
  6136.  
  6137. You can use the AEGetInteractionAllowed function to get the current user interaction preferences for responding to an Apple event.
  6138. FUNCTION AEGetInteractionAllowed 
  6139.                                 (VAR level: AEInteractAllowed): OSErr;
  6140. level    The current user interaction level, using the data type AEInteractAllowed.
  6141.     TYPE AEInteractAllowed = (kAEInteractWithSelf, 
  6142.                           kAEInteractWithLocal, 
  6143.                           kAEInteractWithAll);
  6144. DESCRIPTION
  6145. The AEGetInteractionAllowed function returns, in the level parameter, a value that indicates the user interaction preferences for responding to an Apple event. The value, set by a previous call to AESetInteractionAllowed, is one of the following flags: kAEInteractWithSelf, kAEInteractWithLocal, or kAEInteractWithAll. The default value of kAEInteractWithLocal is returned if your application has not used AESetInteractionAllowed to set the interaction level explicitly. 
  6146. The kAEInteractWithSelf flag indicates that the server application may interact with the user in response to an Apple event only when the client application and server application are the same—that is, only when the application is sending the Apple event to itself.
  6147. The kAEInteractWithLocal flag indicates that the server application may interact with the user in response to an Apple event only if the client application is on the same computer as the server application. This is the default if your application has not used the AESetInteractionAllowed function to set the interaction level explicitly.
  6148. The kAEInteractWithAll flag indicates that the server application may interact with the user in response to an Apple event sent from any client application on any computer.
  6149. RESULT CODEnoErr    0    No error    
  6150.  
  6151. AEInteractWithUser
  6152.  
  6153. You can use the AEInteractWithUser function to initiate interaction with the user when your application is a server application responding to an Apple event.
  6154. FUNCTION AEInteractWithUser (timeOutInTicks: LongInt; 
  6155.                                       nmReqPtr: NMRecPtr; 
  6156.                                       idleProc: IdleProcPtr): OSErr;
  6157. timeOutInTicks 
  6158. The amount of time (in ticks) that your handler is willing to wait for a response from the user. You can specify a number of ticks or use one of the following constants:
  6159.     CONST kAEDefaultTimeout = -1; {value determined }
  6160.                                                       { by AEM}
  6161.       kNoTimeOut        = -2; {wait until reply }
  6162.                               { comes back}
  6163. nmReqPtr     A pointer to a Notification Manager record provided by your application. You can specify NIL for this parameter to get the default notification handling provided by the Apple Event Manager.
  6164. idleProc     A pointer to your application’s idle function, which handles events while waiting for the Apple Event Manager to return control. 
  6165. DESCRIPTION
  6166. Your application should call the AEInteractWithUser function before displaying a dialog box or alert box or otherwise interacting with the user in response to an Apple event. If the user interaction preference settings permit the application to come to the foreground, this function brings your application to the front, either directly or by posting a notification request.
  6167. Your application should normally pass a notification record in the nmReqPtr parameter rather than specifying NIL for default notification handling. If you specify NIL, the Apple Event Manager looks for an application icon with the ID specified by the application’s bundle ('BNDL') resource and the application’s file reference ('FREF') resource. The Apple Event Manager first looks for an 'SICN' resource with the specified ID; if it can’t find an 'SICN' resource, it looks for the 'ICN#' resource and compresses the icon to fit in the menu bar. The Apple Event Manager won’t look for any members of an icon family other than the icon specified in the 'ICN#' resource.
  6168. If the application doesn’t have 'SICN' or 'ICN#' resources, or if it doesn’t have a file reference resource, the Apple Event Manager passes NIL to the Notification Manager, and no icon appears in the upper-right corner of the screen. Therefore, if you want to display any icon other than those of type 'SICN' or 'ICN#', you must specify a notification record as the second parameter to the AEInteractWithUser function.
  6169. Note
  6170. Note
  6171. If you want the Notification Manager to use a color icon when it posts a notification request, you should provide a Notification Manager record that specifies a 'cicn' resource.u
  6172. The AEInteractWithUser function checks whether the client application set the kAENeverInteract flag for the Apple event and, if so, returns an error. If not, then the AEInteractWithUser function checks the server application’s preference set by the AESetInteractionAllowed function and compares it against the source of the Apple event—that is, whether it came from the same application, another process on the same computer, or a process running on another computer. The AEInteractWithUser function returns the errAENoUserInteraction result code if the user interaction preferences don’t allow user interaction. If user interaction is allowed, the Apple Event Manager brings your application to the front, either directly or by posting a notification request. If AEInteractWithUser returns the noErr result code, then your application is in the foreground and is free to interact with the user.
  6173. RESULT CODESnoErr    0    No error    
  6174. errAETimeout    –1712    Apple event timed out    
  6175. errAENoUserInteraction    –1713    No user interaction allowed    
  6176.  
  6177. SEE ALSO
  6178. For information about idle functions, see “Writing an Idle Function” on page 5-21.
  6179. For examples of the use of the AEInteractWithUser function, see “Interacting With the User,” which begins on page 4-45.
  6180. Requesting More Time to Respond to Apple Events
  6181.  
  6182. The AEResetTimer function resets the timeout value for an Apple event to its starting value. A server application can call this function when it knows it cannot fulfill a client application’s request (either by returning a result or by sending back a reply Apple event) before the client application is due to time out.
  6183. AEResetTimer
  6184.  
  6185. You can use the AEResetTimer function to reset the timeout value for an Apple event to its starting value.
  6186. FUNCTION AEResetTimer (reply: AppleEvent): OSErr;
  6187. reply    The default reply for an Apple event, provided by the Apple Event Manager.
  6188. DESCRIPTION
  6189. When your application calls AEResetTimer, the Apple Event Manager for the server application uses the default reply to send a Reset Timer event to the client application; the Apple Event Manager for the client application’s computer intercepts this Apple event and resets the client application’s timer for the Apple event. (The Reset Timer event is never dispatched to a handler, so the client application does not need a handler for it.)
  6190. RESULT CODEnoErr    0    No error    
  6191. errAEReplyNotValid    –1709    AEResetTimer was passed an invalid reply     
  6192.  
  6193. Suspending and Resuming Apple Event Handling
  6194.  
  6195. When your application calls AEProcessAppleEvent and one of your event handlers is invoked, the Apple Event Manager normally assumes that your application has finished handling the event when the event handler returns. At this point, the Apple Event Manager disposes of the event. However, some applications, such as multi-session servers or any applications that implement their own internal event queueing, may need to defer handling of the event.
  6196. The AESuspendTheCurrentEvent, AEResumeTheCurrentEvent, AESetTheCurrentEvent, and AEGetTheCurrentEvent functions described in this section allow you to suspend and resume Apple event handling, specify the Apple event to be handled, and identify an Apple event that is currently being handled. 
  6197. AESuspendTheCurrentEvent
  6198.  
  6199. You can use the AESuspendTheCurrentEvent function to suspend the processing of the Apple event that is currently being handled. 
  6200. FUNCTION AESuspendTheCurrentEvent 
  6201.                                     (theAppleEvent: AppleEvent): OSErr;
  6202. theAppleEvent
  6203. The Apple event whose handling is to be suspended. Although the Apple Event Manager doesn’t need this parameter to identify the Apple event currently being handled, providing it is a safeguard that you are suspending the correct Apple event.
  6204. DESCRIPTION
  6205. After a server application makes a successful call to the AESuspendTheCurrentEvent function, it is no longer required to return a result or a reply for the Apple event that was being handled. It can, however, return a result if it later calls the AEResumeTheCurrentEvent function to resume event processing.
  6206. The Apple Event Manager does not automatically dispose of Apple events that have been suspended or their default replies. (The Apple Event Manager does, however, automatically dispose of a previously suspended Apple event and its default reply if the server later resumes processing of the Apple event by calling the AEResumeTheCurrentEvent function.) If your server application does not resume processing of a suspended Apple event, it is responsible for using the AEDisposeDesc function to dispose of both the Apple event and its default reply when your application has finished using them.
  6207. SPECIAL CONSIDERATIONS
  6208. If your application suspends handling of an Apple event it sends to itself, the Apple Event Manager immediately returns from the AESend call with the error code errAETimeout, regardless of whether the kAEQueueReply, kAEWaitReply, or kAENoReply flags were set, even if the timeout parameter is set to kNoTimeOut. The routine calling AESend should take the timeout error as confirmation that the event was sent.
  6209. As with other calls to AESend that return a timeout error, the handler continues to process the event nevertheless. The handler’s reply, if any, is provided in the reply event when the handling is completed. The Apple Event Manager provides no notification that the reply is ready. If no data has yet been placed in the reply event, the Apple Event Manager returns errAEReplyNotArrived when your application attempts to extract data from the reply.
  6210. RESULT CODEnoErr    0    No error    
  6211.  
  6212. AEResumeTheCurrentEvent
  6213.  
  6214. You can use the AEResumeTheCurrentEvent function to inform the Apple Event Manager that your application wants to resume the handling of a previously suspended Apple event or that it has completed the handling of the Apple event.
  6215. FUNCTION AEResumeTheCurrentEvent 
  6216.                                     (theAppleEvent, reply: AppleEvent; 
  6217.                                      dispatcher: EventHandlerProcPtr; 
  6218.                                      handlerRefcon: LongInt): OSErr;
  6219. theAppleEvent
  6220. The Apple event to be resumed.
  6221. reply     The default reply provided by the Apple Event Manager for the Apple event.
  6222. dispatcher
  6223. One of the following:
  6224. n    a pointer to a routine for handling the event
  6225. n    the kAEUseStandardDispatch constant, which tells the Apple Event Manager to dispatch the resumed event using the standard dispatching scheme it uses for other Apple events
  6226. n    the kAENoDispatch constant, which tells the Apple Event Manager that the Apple event has been completely processed and need not be dispatched
  6227. handlerRefcon 
  6228. If the value of the dispatcher parameter is not kAEUseStandardDispatch, this parameter is the reference constant passed to the handler when the handler is called. If the value of the dispatcher parameter is kAEUseStandardDispatch, the Apple Event Manager ignores the handlerRefcon parameter and instead passes the reference constant stored in the Apple event dispatch table entry for the Apple event. (You may wish to pass the same reference constant that is stored in the Apple event dispatch table. If so, call the AEGetEventHandler function.)
  6229. DESCRIPTION
  6230. When your application calls the AEResumeTheCurrentEvent function, the Apple Event Manager resumes handling the specified Apple event using the handler specified in the dispatcher parameter, if any. If kAENoDispatch is specified in the dispatcher parameter, AEResumeTheCurrentEvent simply informs the Apple Event Manager that the specified event has been handled.
  6231. SPECIAL CONSIDERATIONS
  6232. An Apple event handler that suspends an event should not immediately call AEResumeTheCurrentEvent, or else the handler will generate an error. Instead, the handler should return just after suspending the event.
  6233. When your application calls AEResumeTheCurrentEvent for an event that was not directly dispatched, the Apple Event Manager disposes of the event and the reply, just as it normally does, after the event handler returns to AEProcessAppleEvent. Make sure all processing involving the event or the reply has been completed before your application calls AEResumeTheCurrentEvent. Do not call AEResumeTheCurrentEvent for an event that was not suspended.
  6234. When your application calls AEResumeTheCurrentEvent for an event that was directly dispatched, your application is responsible for disposing of the original event and the reply, since it is acts as both the server and the client.
  6235. RESULT CODEnoErr    0    No error    
  6236.  
  6237. AESetTheCurrentEvent
  6238.  
  6239. You can use the AESetTheCurrentEvent function to specify the Apple event to be handled.
  6240. FUNCTION AESetTheCurrentEvent (theAppleEvent: AppleEvent): OSErr;
  6241. theAppleEvent
  6242. The Apple event to be handled.
  6243. DESCRIPTION
  6244. There is usually no reason for your application to use the AESetTheCurrentEvent function. Instead of calling this function, your application should let the Apple Event Manager set the current Apple event through the dispatch tables.
  6245. If you need to avoid the dispatch tables, you must use the AESetTheCurrentEvent function only in the following way:
  6246.     1.    Your application suspends handling of an Apple event by calling the AESuspendTheCurrentEvent function.
  6247.     2.    Your application calls the AESetTheCurrentEvent function. This informs the Apple Event Manager that your application is handling the suspended Apple event. In this way, any routines that call the AEGetTheCurrentEvent function can ascertain which event is currently being handled.
  6248.     3.    When your application finishes handling the Apple event, it calls the AEResumeTheCurrentEvent function with the value kAENoDispatch to tell the Apple Event Manager that the event has been processed and need not be dispatched.
  6249. RESULT CODEnoErr    0    No error    
  6250.  
  6251. AEGetTheCurrentEvent
  6252.  
  6253. You can use the AEGetTheCurrentEvent function to get the Apple event that is currently being handled. 
  6254. FUNCTION AEGetTheCurrentEvent 
  6255.                                 (VAR theAppleEvent: AppleEvent): OSErr;
  6256. theAppleEvent
  6257. The Apple event that is currently being handled; if no Apple event is currently being handled, AEGetTheCurrentEvent returns a null descriptor record in this parameter.
  6258. DESCRIPTION
  6259. In many applications, the handling of an Apple event involves one or more long chains of calls to internal routines. The AEGetTheCurrentEvent function makes it unnecessary for these calls to include the current Apple event as a parameter; the routines can simply call AEGetTheCurrentEvent to get the current Apple event when it is needed.
  6260. You can also use the AEGetTheCurrentEvent function to make sure that no Apple event is currently being handled. For example, suppose your application always uses an application-defined routine to delete a file. That routine can first call AEGetTheCurrentEvent and delete the file only if AEGetTheCurrentEvent returns a null descriptor record (that is, only if no Apple event is currently being handled).
  6261. RESULT CODEnoErr    0    No error    
  6262.  
  6263. Getting the Sizes and Descriptor Types of Descriptor Records
  6264.  
  6265. The Apple Event Manager provides four routines that allow you to get the sizes and descriptor types of descriptor records that are not part of an Apple event record. The AESizeOfNthItem function returns the size and descriptor type of a descriptor record in a descriptor list.The AESizeOfKeyDesc function returns the size and descriptor type of a keyword-specified descriptor record in an AE record. You can get the size and descriptor type of an Apple event parameter or Apple event attribute using the AESizeOfParam and AESizeOfAttribute functions.
  6266. AESizeOfNthItem
  6267.  
  6268. You can use the AESizeOfNthItem function to get the size and descriptor type of a descriptor record in a descriptor list. 
  6269. FUNCTION AESizeOfNthItem (theAEDescList: AEDescList; 
  6270.                                   index: LongInt; VAR typeCode: DescType; 
  6271.                                   VAR dataSize: Size): OSErr;
  6272. theAEDescList
  6273. The descriptor list containing the descriptor record.
  6274. index    The position of the descriptor record in the list (for example, 2 specifies the second descriptor record).
  6275. typeCode     The descriptor type of the descriptor record.
  6276. dataSize     The length (in bytes) of the data in the descriptor record.
  6277. RESULT CODESnoErr    0    No error    
  6278. errAEDescNotFound     –1701    Descriptor record was not found    
  6279. errAEReplyNotArrived    –1718    Reply has not yet arrived     
  6280.  
  6281. AESizeOfKeyDesc
  6282.  
  6283. You can use the AESizeOfKeyDesc function to get the size and descriptor type of a keyword-specified descriptor record in an AE record. 
  6284. FUNCTION AESizeOfKeyDesc (theAERecord: AERecord; 
  6285.                                   theAEKeyword: AEKeyword; 
  6286.                                   VAR typeCode: DescType; 
  6287.                                   VAR dataSize: Size): OSErr;
  6288. theAERecord
  6289. The AE record containing the desired keyword-specified descriptor record.
  6290. theAEKeyword
  6291. The keyword that specifies the desired descriptor record.
  6292. typeCode     The descriptor type of the keyword-specified descriptor record.
  6293. dataSize     The length, in bytes of the data in the keyword-specified descriptor record.
  6294. RESULT CODESnoErr    0    No error    
  6295. errAEDescNotFound    –1701    Descriptor record was not found    
  6296. errAENotAEDesc    –1704    Not a valid descriptor record    
  6297. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  6298.  
  6299. AESizeOfParam
  6300.  
  6301. You can use the AESizeOfParam function to get the size and descriptor type of an Apple event parameter. 
  6302. FUNCTION AESizeOfParam (theAppleEvent: AppleEvent; theAEKeyword: 
  6303.                                 AEKeyword; VAR typeCode: DescType; 
  6304.                                 VAR dataSize: Size): OSErr;
  6305. theAppleEvent
  6306. The Apple event containing the parameter.
  6307. theAEKeyword
  6308. The keyword that specifies the desired parameter.
  6309. typeCode     The descriptor type of the Apple event parameter.
  6310. dataSize     The length, in bytes, of the data in the Apple event parameter.
  6311. RESULT CODESnoErr    0    No error    
  6312. errAEDescNotFound    –1701    Descriptor record was not found    
  6313. errAENotAEDesc    –1704    Not a valid descriptor record    
  6314. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  6315.  
  6316. AESizeOfAttribute
  6317.  
  6318. You can use the AESizeOfAttribute function to get the size and descriptor type of an Apple event attribute.
  6319. FUNCTION AESizeOfAttribute (theAppleEvent: AppleEvent; 
  6320.                                      theAEKeyword: AEKeyword; 
  6321.                                      VAR typeCode: DescType; 
  6322.                                      VAR dataSize: Size): OSErr;
  6323. theAppleEvent
  6324. The Apple event containing the desired attribute.
  6325. theAEKeyword
  6326. The keyword that specifies the attribute.
  6327. typeCode     The descriptor type of the attribute.
  6328. dataSize     The length, in bytes, of the data in the attribute.
  6329. RESULT CODESnoErr    0    No error    
  6330. errAEDescNotFound    –1701    Descriptor record was not found    
  6331. errAENotAEDesc    –1704    Not a valid descriptor record    
  6332. errAEReplyNotArrived    –1718    Reply has not yet arrived       
  6333.  
  6334. Deleting Descriptor Records
  6335.  
  6336. The Apple Event Manager provides three functions that allow you to delete descriptor records. The AEDeleteItem, AEDeleteKeyDesc, and AEDeleteParam functions allow you to delete descriptor records from a descriptor list, an AE record, and an Apple event parameter, respectively. 
  6337. AEDeleteItem
  6338.  
  6339. You can use the AEDeleteItem function to delete a descriptor record from a descriptor list. All subsequent descriptor records will then move up one place. 
  6340. FUNCTION AEDeleteItem (theAEDescList: AEDescList; 
  6341.                               index: LongInt): OSErr;
  6342. theAEDescList
  6343. The descriptor list containing the descriptor record to be deleted.
  6344. index    The position of the descriptor record to delete (for example, 2 specifies the second item).
  6345. RESULT CODESnoErr    0    No error    
  6346. errAEDescNotFound    –1701    Descriptor record was not found    
  6347. errAENotAEDesc    –1704    Not a valid descriptor record    
  6348. errAEBadListItem    –1705    Operation involving a list item failed    
  6349.  
  6350. AEDeleteKeyDesc
  6351.  
  6352. You can use the AEDeleteKeyDesc function to delete a keyword-specified descriptor record from an AE record.
  6353. FUNCTION AEDeleteKeyDesc (theAERecord: AERecord; 
  6354.                                   theAEKeyword: AEKeyword): OSErr;
  6355. theAERecord
  6356. The AE record containing the keyword-specified descriptor record to be deleted.
  6357. theAEKeyword
  6358. The keyword that specifies the descriptor record to be deleted.
  6359. RESULT CODESnoErr    0    No error    
  6360. errAEDescNotFound    –1701    Descriptor record was not found    
  6361. errAENotAEDesc    –1704    Not a valid descriptor record    
  6362. errAEBadListItem    –1705    Operation involving a list item failed    
  6363.  
  6364. AEDeleteParam
  6365.  
  6366. You can use the AEDeleteParam function to delete an Apple event parameter.
  6367. FUNCTION AEDeleteParam (theAppleEvent: AppleEvent; 
  6368.                                 theAEKeyword: AEKeyword): OSErr;
  6369. theAppleEvent
  6370. The Apple event containing the parameter to be deleted.
  6371. theAEKeyword
  6372. The keyword that specifies the parameter to be deleted.
  6373. RESULT CODESnoErr    0    No error    
  6374. errAEDescNotFound    –1701    Descriptor record was not found    
  6375. errAENotAEDesc    –1704    Not a valid descriptor record    
  6376. errAEBadListItem    –1705    Operation involving a list item failed    
  6377.  
  6378. Deallocating Memory for Descriptor Records
  6379.  
  6380. The AEDisposeDesc function deallocates the memory used by a descriptor record. Because all Apple event structures (except for keyword-specified descriptor records) are descriptor records, you can use AEDisposeDesc for any of them.
  6381. AEDisposeDesc
  6382.  
  6383. You can use the AEDisposeDesc function to deallocate the memory used by a descriptor record. 
  6384. FUNCTION AEDisposeDesc (VAR theAEDesc: AEDesc): OSErr;
  6385. theAEDesc     The descriptor record to deallocate. The function returns a null descriptor record in this parameter. If you pass a null descriptor record in this parameter, AEDisposeDesc returns noErr.
  6386. RESULT CODEnoErr    0    No error    
  6387.  
  6388. SEE ALSO
  6389. For more information about using AEDisposeDesc, see “Disposing of Apple Event Data Structures,” which begins on page 4-39.
  6390. Coercing Descriptor Types
  6391.  
  6392. The Apple Event Manager provides two functions that allow you to coerce descriptor types. The AECoercePtr function takes a pointer to data and a desired descriptor type and attempts to coerce the data to a descriptor record of the desired descriptor type. The AECoerceDesc function attempts to coerce the data in an existing descriptor record to another descriptor type. 
  6393. AECoercePtr
  6394.  
  6395. You can use the AECoercePtr function to coerce data to a desired descriptor type. If successful, it creates a descriptor record containing the newly coerced data. 
  6396. FUNCTION AECoercePtr (typeCode: DescType; dataPtr: Ptr; 
  6397.                              dataSize: Size; toType: DescType; 
  6398.                              VAR result: AEDesc): OSErr;
  6399. typeCode     The descriptor type of the source data.
  6400. dataPtr     A pointer to the data to be coerced.
  6401. dataSize     The length, in bytes, of the data to be coerced.
  6402. toType    The desired descriptor type of the resulting descriptor record.
  6403. result    The resulting descriptor record. 
  6404. DESCRIPTION
  6405. The AECoercePtr function creates a new descriptor record by coercing the specified data to a descriptor record of the specified descriptor type. You should use the AEDisposeDesc function to dispose of the resulting descriptor record once you are finished using it.
  6406. If AECoercePtr returns a nonzero result code, it returns a null descriptor record unless the Apple Event Manager is not available because of limited memory. 
  6407. RESULT CODESnoErr    0    No error    
  6408. memFullErr    –108    Not enough room in heap zone    
  6409. errAECoercionFail     –1700    Data could not be coerced to the requested descriptor type    
  6410.  
  6411. SEE ALSO
  6412. For a description of the AEDisposeDesc function, see page 4-94.
  6413. AECoerceDesc
  6414.  
  6415. You can use the AECoerceDesc function to coerce the data in a descriptor record to another descriptor type. 
  6416. FUNCTION AECoerceDesc (theAEDesc: AEDesc; toType: DescType; 
  6417.                               VAR result: AEDesc): OSErr;
  6418. theAEDesc    The descriptor record whose data is to be coerced.
  6419. toType    The desired descriptor type of the resulting descriptor record.
  6420. result    The resulting descriptor record.
  6421. DESCRIPTION
  6422. The AECoerceDesc function attempts to create a new descriptor record by coercing the specified descriptor record. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record once you are finished using it.
  6423. If AECoerceDesc returns a nonzero result code, it returns a null descriptor record (a descriptor record of type typeNull, which does not contain any data) unless the Apple Event Manager is not available because of limited memory.
  6424. RESULT CODESnoErr    0    No error    
  6425. memFullErr    –108    Not enough room in heap zone    
  6426. errAECoercionFail    –1700    Data could not be coerced to requested descriptor type    
  6427.  
  6428. SEE ALSO
  6429. For a list of the descriptor types for which the Apple Event Manager provides coercions, see Table 4-1, which begins on page 4-43.
  6430. Creating and Managing the Coercion Handler Dispatch Tables
  6431.  
  6432. The Apple Event Manager provides three functions that allow you to create and manage the coercion handler dispatch tables. The AEInstallCoercionHandler function installs a coercion handler routine in either the application or system coercion dispatch table. The AEGetCoercionHandler function returns the handler for a specified descriptor type coercion. The AERemoveCoercionHandler function removes a coercion handler from either the application or system coercion table.
  6433. AEInstallCoercionHandler
  6434.  
  6435. You can use the AEInstallCoercionHandler function to install a coercion handler routine in either the application or system coercion handler dispatch table.
  6436. FUNCTION AEInstallCoercionHandler (fromType: DescType; 
  6437.                                               toType: DescType; 
  6438.                                               handler: ProcPtr; 
  6439.                                               handlerRefcon: LongInt; 
  6440.                                               fromTypeIsDesc: Boolean; 
  6441.                                               isSysHandler: Boolean): OSErr;
  6442. fromType     The descriptor type of the data coerced by the handler.
  6443. toType     The descriptor type of the resulting data. If there was already an entry in the specified coercion handler table for the same source descriptor type and result descriptor type, the existing entry is replaced.
  6444. handler     A pointer to the coercion handler. Note that a handler in the system coercion table must reside in the system heap; thus, if the value of the isSysHandler parameter is TRUE, the handler parameter should point to a location in the system heap. Otherwise, if you put your system handler code in your application heap, you should use AERemoveCoercionHandler to remove the handler when your application quits.
  6445. handlerRefcon 
  6446. A reference constant passed by the Apple Event Manager to the handler each time the handler is called. If your handler doesn’t expect a reference constant, use 0 as the value of this parameter.
  6447. fromTypeIsDesc 
  6448. Specifies the form of the data to be coerced. If the value of this parameter is TRUE, the coercion handler expects the data to be passed as a descriptor record. If the value is FALSE, the coercion handler expects a pointer to the data. Because it is more efficient for the Apple Event Manager to provide a pointer to data than to a descriptor record, all coercion routines should accept a pointer to data if possible.
  6449. isSysHandler 
  6450. Specifies the coercion table to which the handler is added. If the value of this parameter is TRUE, the handler is added to the system coercion table and made available to all applications. If the value is FALSE, the handler is added to the application coercion table. Note that a handler in the system coercion table must reside in the system heap; thus, if the value of the isSysHandler parameter is TRUE, the handler parameter must point to a location in the system heap.
  6451. DESCRIPTION
  6452. Before using AEInstallCoercionHandler to install a handler for a particular descriptor type into the system coercion handler dispatch table, use the AEGetCoercionHandler function to determine whether the table already contains a coercion handler for that descriptor type. If an entry exists, AEGetCoercionHandler returns a reference constant and a pointer to that handler. Chain these to your coercion handler by providing, in the handlerRefcon parameter of AEInstallCoercionHandler, pointers to the previous handler and its reference constant. If your coercion handler returns the error errAECoercionFail, use these pointers to call the previous handler. If you remove your system coercion handler, be sure to reinstall the chained handlers.
  6453. SPECIAL CONSIDERATIONS
  6454. Before an application calls a system coercion handler, system software has set up the A5 register for the calling application. For this reason, if you provide a system coercion handler, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.
  6455. RESULT CODESnoErr    0    No error    
  6456. memFullErr    –108    Not enough room in heap zone    
  6457.  
  6458. AEGetCoercionHandler
  6459.  
  6460. You can use the AEGetCoercionHandler function to get the handler for a specified descriptor type coercion.
  6461. FUNCTION AEGetCoercionHandler (fromType: DescType; 
  6462.                                          toType: DescType; 
  6463.                                          VAR handler: ProcPtr; 
  6464.                                          VAR handlerRefcon: LongInt; 
  6465.                                           VAR fromTypeIsDesc: Boolean; 
  6466.                                           isSysHandler: Boolean): OSErr;
  6467. fromType    The descriptor type of the data coerced by the handler.
  6468. toType     The descriptor type of the resulting data.
  6469. handler     A pointer to the desired coercion handler.
  6470. handlerRefcon 
  6471. The reference constant for the desired handler. The Apple Event Manager passes this reference constant to the handler each time the handler is called.
  6472. fromTypeIsDesc 
  6473. If the AEGetCoercionHandler function returns TRUE in this parameter, the coercion handler expects the data to be passed as a descriptor record. If the function returns FALSE, the coercion handler expects a pointer to the data.
  6474. isSysHandler 
  6475. Specifies the coercion table from which to get the handler. If the value of this parameter is TRUE, the handler is taken from the system coercion table. If the value is FALSE, the handler is taken from the application coercion table.
  6476. RESULT CODESnoErr    0    No error    
  6477. memFullErr    –108    Not enough room in heap zone    
  6478. errAEHandlerNotFound    –1717    No coercion handler found    
  6479.  
  6480. AERemoveCoercionHandler
  6481.  
  6482. You can use the AERemoveCoercionHandler function to remove a coercion handler from either the application or system coercion handler dispatch table.
  6483. FUNCTION AERemoveCoercionHandler (fromType: DescType; 
  6484.                                              toType: DescType; 
  6485.                                              handler: ProcPtr; 
  6486.                                              isSysHandler: Boolean): OSErr;
  6487. fromType     The descriptor type of the data coerced by the handler.
  6488. toType     The descriptor type of the resulting data.
  6489. handler    A pointer to the coercion handler. Although the fromType and toType parameters would be sufficient to identify the handler to be removed, providing the handler parameter is a safeguard to ensure that you remove the correct handler.
  6490. isSysHandler 
  6491. The coercion table from which to remove the handler. If the value of this parameter is TRUE, the handler is removed from the system coercion table. If the value is FALSE, the handler is removed from the application coercion dispatch table.
  6492. RESULT CODESnoErr    0    No error    
  6493. memFullErr    –108    Not enough room in heap zone    
  6494. errAEHandlerNotFound    –1717    No coercion handler found    
  6495.  
  6496. Creating and Managing the Special Handler Dispatch Tables
  6497.  
  6498. The Apple Event Manager provides three functions that allow you to create and manage the special handler dispatch tables. The AEInstallSpecialHandler function installs an entry for a special handler in either the application or system special handler dispatch table. The AEGetSpecialHandler function returns the handler for a specified special handler. The AERemoveSpecialHandler function removes a special handler from either the application or system special handler dispatch table. 
  6499. You can also use the AEInstallSpecialHandler, AEGetSpecialHandler, and AERemoveSpecialHandler functions to install, get, and remove object callback functions—including system object callback functions, which cannot be installed with the AESetObjectCallbacks function. When calling any of these three functions, use one of the following constants as the value of the functionClass parameter to specify the object callback function:Object callback function    Constant    
  6500. Object-counting function    keyAECountProc    
  6501. Object-comparison function    keyAECompareProc    
  6502. Token disposal function    keyDiposeTokenProc    
  6503. Error callback function    keyAEGetErrDescProc    
  6504. Mark token function    keyAEMarkTokenProc    
  6505. Object-marking function    keyAEMarkProc    
  6506. Mark-adjusting function    keyAEAdjustMarksProc    
  6507.  
  6508. You can also use the AERemoveSpecialHandler function to disable all the Apple Event Manager routines that support object specifier records. To do this, specify the constant keySelectProc in the functionClass parameter as described on page 4-102. 
  6509. AEInstallSpecialHandler
  6510.  
  6511. You can use the AEInstallSpecialHandler function to install a special handler in either the application or system special handler dispatch table.
  6512. FUNCTION AEInstallSpecialHandler (functionClass: AEKeyword; 
  6513.                                              handler: ProcPtr; 
  6514.                                              isSysHandler: Boolean): OSErr;
  6515. functionClass 
  6516. The keyword for the special handler that is installed. The keyPreDispatch constant identifies a handler with the same parameters as an Apple event handler called immediately before the Apple Event Manager dispatches an Apple event. Any of the constants for object callback functions listed above can also be specified in this parameter. If there was already an entry in the specified special handler dispatch table for the same value of functionClass, it is replaced.
  6517. handler     A pointer to the special handler. Note that a handler in the system special handler dispatch table must reside in the system heap; thus, if the value of the isSysHandler parameter is TRUE, the handler parameter should point to a location in the system heap. Otherwise, if you put your system handler code in your application heap, use AERemoveSpecialHandler to remove the handler when your application quits.
  6518. isSysHandler 
  6519. The special handler dispatch table to which to add the handler. If the value of this parameter is TRUE, the handler is added to the system handler dispatch table and made available to all applications. If the value is FALSE, the handler is added to the application handler table.
  6520. DESCRIPTION
  6521. The AEInstallSpecialHandler function creates an entry in either your application’s special handler dispatch table or the system special handler dispatch table. You must supply parameters that specify the keyword for the special handler that is installed, the handler routine, and whether the handler is to be added to the system special handler dispatch table or your application’s special handler dispatch table.
  6522. SPECIAL CONSIDERATIONS
  6523. Before an application calls a system special handler, system software has set up the A5 register for the calling application. For this reason, a system special handler should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system handler may crash.
  6524. RESULT CODESnoErr    0    No error    
  6525. paramErr    –50    Parameter error (handler pointer is NIL or odd)    
  6526. memFullErr    –108    Not enough room in heap zone    
  6527. errAENotASpecialFunction    –1714    Wrong keyword for a special function    
  6528.  
  6529. AEGetSpecialHandler
  6530.  
  6531. You can use the AEGetSpecialHandler function to get a specified special handler.
  6532. FUNCTION AEGetSpecialHandler (functionClass: AEKeyword; 
  6533.                                         VAR handler: ProcPtr; 
  6534.                                         isSysHandler: Boolean): OSErr;
  6535. functionClass 
  6536. The keyword for the special handler that is installed. The keyPreDispatch constant identifies a handler with the same parameters as an Apple event handler that is called immediately before the Apple Event Manager dispatches an Apple event. Any of the constants for object callback functions listed on page 4-100 can also be specified in this parameter. 
  6537. handler     A pointer to the special handler.
  6538. isSysHandler
  6539. Specifies the special handler dispatch table from which to get the handler. If the value of this parameter is TRUE, the handler is taken from the system special handler dispatch table. If the value is FALSE, the handler is taken from the application’s special handler dispatch table.
  6540. RESULT CODESnoErr    0    No error    
  6541. memFullErr    –108    Not enough room in heap zone    
  6542. errAENotASpecialFunction    –1714    Wrong keyword for a special handler    
  6543.  
  6544. AERemoveSpecialHandler
  6545.  
  6546. You can use the AERemoveSpecialHandler function to remove a handler from a special handler table.
  6547. FUNCTION AERemoveSpecialHandler (functionClass: AEKeyword; 
  6548.                                             handler: ProcPtr; 
  6549.                                             isSysHandler: Boolean): OSErr;
  6550. functionClass 
  6551. The keyword for the special handler to be removed. In addition to the constants for object callback functions listed on page 4-100, two other values are allowed for the functionClass parameter: keyPreDispatch and keySelectProc. The keyPreDispatch constant identifies a handler with the same parameters as an Apple event handler that is called immediately before the Apple Event Manager dispatches an Apple event. The keySelectProc constant indicates that you want to disable the Object Support Library—that is, all the routines described in the chapter “Resolving and Creating Object Specifier Records” in this book (see the description that follows for more information).
  6552. handler     A pointer to the special handler to be removed. Although the functionClass parameter would be sufficient to identify the handler to be removed, providing the handler parameter is a safeguard that you remove the correct handler.
  6553. isSysHandler 
  6554. Specifies the special handler dispatch table from which to remove the handler. If the value of this parameter is TRUE, the handler is taken from the system special handler dispatch table. If the value is FALSE, the handler is removed from the application special handler dispatch table.
  6555. DESCRIPTION
  6556. In addition to using the AERemoveSpecialHandler function to remove specific special handlers, you can use the function to disable, within your application only, all Apple Event Manager routines that support Apple event objects—that is, all the routines available to your application as a result of linking the Object Support Library (OSL) and calling the AEObjectInit function. 
  6557. An application that expects its copy of the OSL to move after it is installed—for example, an application that keeps it in a stand-alone code resource—would need to do this. When an application calls AEObjectInit to initialize the OSL, the OSL installs the addresses of its routines as extensions to the pack. If those routines move, the addresses become invalid.
  6558. To disable the OSL, you should pass the keyword keySelectProc in the functionClass parameter, NIL in the handler parameter, and FALSE in the isSysHandler parameter. Once you have called the AERemoveSpecialHandler function with these parameters, subsequent calls by your application to any of the Apple Event Manager routines that support Apple event objects will return errors. To initialize the OSL after disabling it with the AERemoveSpecialHandler function, your application must call AEObjectInit again.
  6559. If you expect to initialize the OSL and disable it several times, you should call AERemoveObjectAccessor to remove your application’s object accessor functions from your application’s object accessor dispatch table before you call AERemoveSpecialHandler. 
  6560. RESULT CODESnoErr    0    No error    
  6561. memFullErr    –108    Not enough room in heap zone    
  6562. errAENotASpecialFunction    –1714    Wrong keyword for a special function     
  6563.  
  6564. Getting Information About the Apple Event Manager
  6565.  
  6566. The AEManagerInfo routine allows you to get two kinds of information related to Apple events on the current computer: the number of processes currently recording Apple events and the version of the Apple Event Manager. If you decide to make your application recordable, this information may be useful when your application is responding to Apple events that it sends to itself.
  6567. You can find out whether the Apple Event Manager is available in system software by using the Gestalt function. See page 4-4 for details.
  6568. AEManagerInfo
  6569.  
  6570. You can use the AEManagerInfo function to obtain information about the version of the Apple Event Manager currently available or the number of processes that are currently recording Apple events. This function is available only in version 1.01 and later versions of the Apple Event Manager. 
  6571. FUNCTION AEManagerInfo (keyword: AEKeyword; 
  6572.                                 VAR result: LongInt): OSErr;
  6573. keyword    A value that determines what kind of information AEManagerInfo returns. The value can be represented by one of these constants:
  6574.     CONST keyAERecorderCount         = 'recr'; 
  6575.                                       keyAEVersion                                   =     'vers'; 
  6576. result    If the value of the keyword parameter is keyAERecorderCount, this parameter is an integer that indicates the number of processes that are currently recording Apple events. If the value of the keyword parameter is keyAEVersion, this parameter is an integer that provides information about the version of the Apple Event Manager available on the current computer, using the same format as a 'vers' resource. 
  6577. RESULT CODEnoErr    0    No error    
  6578.  
  6579. SEE ALSO
  6580. For information about using the AEManagerInfo function to check whether Apple event recording is on or not, see the chapter “Recording Apple Events” in this book.   
  6581. For information about using Gestalt to determine whether the Apple Event Manager is available, see “Handling Apple Events” on page 4-4.
  6582. For information about the 'vers' resource, see the chapter “Finder Interface” in Inside Macintosh: Macintosh Toolbox Essentials.
  6583. Application-Defined Routines
  6584.  
  6585. For each Apple event your application supports, you must provide an Apple event handler. The AEProcessAppleEvent function calls one of your Apple event handlers when it processes an Apple event. An Apple event handler (MyEventHandler) should perform any action described by the Apple event, add parameters to the reply Apple event if appropriate, and return a result code.
  6586. You can also provide your own coercion handlers to coerce data to descriptor types other than those for which the Apple Event Manager provides coercion handling. The MyCoercePtr function accepts a pointer to data and returns a descriptor record, and the MyCoerceDesc function accepts a descriptor record and returns a descriptor record.
  6587. MyEventHandler
  6588.  
  6589. An Apple event handler has the following syntax:
  6590. FUNCTION MyEventHandler (theAppleEvent: AppleEvent; 
  6591.                                  reply: AppleEvent; 
  6592.                                  handlerRefcon: LongInt): OSErr;
  6593. theAppleEvent
  6594. The Apple event to handle.
  6595. reply    The default reply Apple event provided by the Apple Event Manager.
  6596. handlerRefcon
  6597. The reference constant stored in the Apple event dispatch table for the Apple event.
  6598. DESCRIPTION
  6599. An Apple event handler should extract any parameters and attributes from the Apple event, perform the requested action, and add parameters to the reply Apple event if appropriate. 
  6600. Your handler should always set its function result to noErr if it successfully handles the Apple event. If an error occurs, your handler should return either errAEEventNotHandled or some other nonzero result code. If the error occurs because your application cannot understand the event, return errAEEventNotHandled, in case a handler in the system special handler or system Apple event dispatch tables might be able to handle the event. If the error occurs because the event is impossible to handle as specified, return the result code returned by whatever function caused the failure, or whatever other result code is appropriate.
  6601. For example, suppose your application receives a Get Data event that requests the name of the current printer, and your application cannot handle such an event. In this situation, you should return errAEEventNotHandled in case another handler available to the Apple Event Manager can handle the event. This strategy allows users to take advantage of system capabilities from within your application via system handlers. 
  6602. However, if your application cannot handle a Get Data event that requests the fifth paragraph in a document because the document contains only four paragraphs, you should return some other nonzero error, because further attempts to handle the event are pointless.
  6603. If your Apple event handler calls the AEResolve function and AEResolve calls an object accessor function in the system object accessor dispatch table, your Apple event handler may not recognize the descriptor type of the token returned by the function. In this case, your handler should return the result code errAEUnknownObjectType. When your handler returns this result code, the Apple Event Manager attempts to locate a system Apple event handler that can recognize the token. 
  6604. SEE ALSO
  6605. For more information about Apple event handlers, see “Writing Apple Event Handlers” on page 4-33.
  6606. For a discussion of the dispatching of object accessor functions and the use of the result code errAEUnknownObjectType, see “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 6-21. 
  6607. MyCoercePtr
  6608.  
  6609. A coercion handler that accepts a pointer to data has the following syntax:
  6610. FUNCTION MyCoercePtr (typeCode: DescType; dataPtr: Ptr; 
  6611.                              dataSize: Size; toType: DescType; 
  6612.                              handlerRefcon: LongInt;
  6613.                              VAR result: AEDesc): OSErr; 
  6614. typeCode    The descriptor type of the original data.
  6615. dataPtr    A pointer to the data to coerce.
  6616. dataSize    The length, in bytes, of the data to coerce.
  6617. toType    The desired descriptor type for the resulting descriptor record.
  6618. handlerRefcon
  6619. A reference constant that is stored in the coercion dispatch table entry for the handler and passed to the handler by the Apple Event Manager whenever the handler is called.
  6620. result    The resulting descriptor record.
  6621. DESCRIPTION
  6622. Your coercion handler should coerce the data to the desired descriptor type and return the resulting data in the descriptor record specified by the result parameter. Your handler should return the noErr result code if your handler successfully performs the coercion, and a nonzero result code otherwise.
  6623. SEE ALSO
  6624. For more information, see “Writing and Installing Coercion Handlers” on page 4-41.
  6625. MyCoerceDesc
  6626.  
  6627. A coercion handler that accepts a descriptor record has the following syntax:
  6628. FUNCTION MyCoerceDesc (theAEDesc: AEDesc; toType: DescType;
  6629.                                 handlerRefcon: LongInt;
  6630.                                  VAR result: AEDesc): OSErr;
  6631. theAEDesc    The descriptor record that contains the data to be coerced.
  6632. toType    The desired descriptor type for the resulting descriptor record.
  6633. handlerRefcon
  6634. A reference constant that is stored in the coercion dispatch table entry for the handler and passed to the handler by the Apple Event Manager whenever the handler is called.
  6635. result    The resulting descriptor record.
  6636. DESCRIPTION
  6637. Your coercion handler should coerce the data in the descriptor record to the desired descriptor type and return the resulting data in the descriptor record specified by the result parameter. Your handler should return an appropriate result code.
  6638. SEE ALSO
  6639. For more information, see “Writing and Installing Coercion Handlers” on page 4-41.
  6640.  
  6641.  
  6642. Summary of Responding to Apple Events
  6643.  
  6644. Pascal Summary
  6645.  
  6646. Constants
  6647.  
  6648. CONST        
  6649.     gestaltAppleEventsAttr                                    = 'evnt';                {selector for Apple events}
  6650.     gestaltAppleEventsPresent                                    = 0;                {if this bit is set, then Apple }
  6651.                                                         { Event Manager is available}
  6652.  
  6653.     {Apple event descriptor types}
  6654.     typeBoolean                                = 'bool';                    {1-byte Boolean value}
  6655.     typeChar                                = 'TEXT';                    {unterminated string}
  6656.     typeSMInt                                = 'shor';                    {16-bit integer}
  6657.     typeInteger                                = 'long';                    {32-bit integer}
  6658.     typeSMFloat                                = 'sing';                    {SANE single}
  6659.     typeFloat                                = 'doub';                    {SANE double}
  6660.     typeLongInteger                                = 'long';                    {32-bit integer}
  6661.     typeShortInteger                                = 'shor';                    {16-bit integer}
  6662.     typeLongFloat                                = 'doub';                    {SANE double}
  6663.     typeShortFloat                                = 'sing';                    {SANE single}
  6664.     typeExtended                                = 'exte';                    {SANE extended}
  6665.     typeComp                                = 'comp';                    {SANE comp}
  6666.     typeMagnitude                                = 'magn';                    {unsigned 32-bit integer}
  6667.     typeAEList                                = 'list';                    {list of descriptor records}
  6668.     typeAERecord                                = 'reco';                    {list of keyword-specified }
  6669.                                                         { descriptor records}
  6670.     typeAppleEvent                                = 'aevt';                    {Apple event record}
  6671.     typeTrue                                = 'true';                    {TRUE Boolean value}
  6672.     typeFalse                                = 'fals';                    {FALSE Boolean value}
  6673.     typeAlias                                = 'alis';                    {alias record}
  6674.     typeEnumerated                                = 'enum';                    {enumerated data}
  6675.     typeType                                = 'type';                    {four-character code for }
  6676.                                                         { event class or event ID}
  6677.     typeAppParameters                                = 'appa';                    {Process Manager launch parameters}
  6678.     typeProperty                                = 'prop';                    {Apple event property}
  6679.     typeFSS                                = 'fss ';                    {file system specification}
  6680.     typeKeyword                                = 'keyw';                    {Apple event keyword}
  6681.     typeSectionH                                = 'sect';                    {handle to a section record}
  6682.     typeWildCard                                = '****';                    {matches any type}
  6683.     typeApplSignature                                = 'sign';                    {application signature}
  6684.     typeSessionID                                = 'ssid';                    {session reference number}
  6685.     typeTargetID                                = 'targ';                    {target ID record}
  6686.     typeProcessSerialNumber                                = 'psn ';                    {process serial number}
  6687.     typeNull                                = 'null';                    {NULL or nonexistent data}
  6688.     
  6689.     {keywords for Apple event parameters}
  6690.     keyDirectObject                                = '----';                    {direct parameter}
  6691.     keyErrorNumber                                = 'errn';                    {error number parameter}
  6692.     keyErrorString                                = 'errs';                    {error string parameter}
  6693.     keyProcessSerialNumber                                = 'psn ';                    {process serial number param}
  6694.  
  6695.     {keywords for Apple event attributes}
  6696.     keyTransactionIDAttr                                = 'tran';                    {transaction ID}
  6697.     keyReturnIDAttr                                = 'rtid';                    {return ID}
  6698.     keyEventClassAttr                                 = 'evcl';                    {event class}
  6699.     keyEventIDAttr                                = 'evid';                    {event ID}
  6700.     keyAddressAttr                                = 'addr';                    {address of target or }
  6701.                                                         { client application}
  6702.     keyOptionalKeywordAttr                                = 'optk';                    {list of optional parameters }
  6703.                                                         { for the Apple event}
  6704.     keyTimeoutAttr                                = 'timo';                    {number of ticks the client }
  6705.                                                         { will wait}
  6706.     keyInteractLevelAttr                                 = 'inte';                    {settings to allow Apple Event }
  6707.                                                         { Manager to bring server }                    
  6708.                                                         { to foreground}
  6709.     keyEventSourceAttr                                = 'esrc';                    {nature of source }
  6710.                                                         { application}
  6711.     keyMissedKeywordAttr                                = 'miss';                    {first required parameter }
  6712.                                                         { remaining in an Apple event}
  6713.     keyOriginalAddressAttr                                = 'from';                    {address of original source; }
  6714.                                                         { available only in version } 
  6715.                                                         { 1.01 and later versions of }
  6716.                                                         { the Apple Event Manager}
  6717.  
  6718.     {keywords for special handlers}
  6719.     keyPreDispatch                                = 'phac';                    {identifies a handler routine }
  6720.                                                         { called immediately before the }
  6721.                                                         { Apple Event Manager dispatches }
  6722.                                                         { an Apple event}
  6723.     keySelectProc                                = 'selh';                     {selector used with }
  6724.                                                         { AERemoveSpecialHandler to }
  6725.                                                         { disable the OSL}
  6726.  
  6727.     {keywords for use with AEManagerInfo; available only in version }
  6728.     { 1.0.1 and later versions of the Apple Event Manager}
  6729.     keyAERecorderCount                                 = 'recr';                    {keyword for recording info}
  6730.     keyAEVersion                                 = 'vers';                    {keyword for version info}
  6731.  
  6732.     {event class}
  6733.     kCoreEventClass                                = 'aevt';                    {event class for required Apple }
  6734.                                                         { events}
  6735.  
  6736.     {event IDs for required Apple events}
  6737.     kAEOpenApplication                                = 'oapp';                    {event ID for Open }
  6738.                                                         { Application event}
  6739.     kAEOpenDocuments                                = 'odoc';                    {event ID for Open Documents event}
  6740.     kAEPrintDocuments                                = 'pdoc';                    {event ID for Print Documents }
  6741.                                                         { event}
  6742.     kAEQuitApplication                                = 'quit';                    {event ID for Quit Application }
  6743.                                                         { event}
  6744.     kAEAnswer                                = 'ansr';                    {event ID for Apple event replies}
  6745.     kAEApplicationDied                                = 'obit';                    {event ID for Application Died }
  6746.                                                         { event}
  6747.  
  6748.     {constants for setting the sendMode parameter of AESend}
  6749.     kAENoReply                                = $00000001;                    {client doesn't want reply}
  6750.     kAEQueueReply                                = $00000002;                    {client wants server to }
  6751.                                                         { reply in event queue}
  6752.     kAEWaitReply                                = $00000003;                    {client wants a reply and }
  6753.                                                         { will give up processor}
  6754.     kAENeverInteract                                = $00000010;                    {server application should }
  6755.                                                         { not interact with user }
  6756.                                                         { for this Apple event}
  6757.     kAECanInteract                                = $00000020;                    {server may interact with }
  6758.                                                         { user for this Apple event }
  6759.                                                         { to supply information}
  6760.  
  6761.     kAEAlwaysInteract                                = $00000030;                    {server may interact with user }
  6762.                                                         { for this Apple event even if }
  6763.                                                         { no information is required}
  6764.     kAECanSwitchLayer                                = $00000040;                    {server should come directly }
  6765.                                                         { to foreground when appropriate}
  6766.     kAEDontReconnect                                = $00000080;                    {don't reconnect if there }
  6767.                                                         { is a PPC session closed error}
  6768.     kAEWantReceipt                                = nReturnReceipt; {client wants return }
  6769.                                                         { receipt}
  6770.     kAEDontRecord                                = $00001000            ;        {don't record this event}
  6771.     kAEDontExecute                                = $00002000;                    {don't excecute this event}
  6772.  
  6773.     {constants for setting the sendPriority parameter of AESend}
  6774.     kAENormalPriority                                = $00000000;                    {put event at the back of }
  6775.                                                         { event queue}
  6776.     kAEHighPriority                                = nAttnMsg;                    {put event at the front of }
  6777.                                                         { the event queue}
  6778.  
  6779.     {event IDs for recording events; available only in version 1.01 and }
  6780.     { later versions of the Apple Event Manager}
  6781.     kAEStartRecording                                = 'reca';                    {event ID for Start Recording }
  6782.                                                         { event}
  6783.     kAEStopRecording                                = 'recc';                    {event ID for Stop Recording }
  6784.                                                         { event}
  6785.     kAENotifyStartRecording                                = 'rec1';                    {event ID for Recording On event}
  6786.     kAENotifyStopRecording                                = 'rec0';                    {event ID for Recording Off event}
  6787.     kAENotifyRecording                                = 'recr';                    {event ID for Receive Recordable }
  6788.                                                         { Event event}
  6789.  
  6790.     {constant for the returnID parameter of AECreateAppleEvent}
  6791.     kAutoGenerateReturnID                                = -1;                    {tells Apple Event Manager to }
  6792.                                                         { generate a unique return ID}
  6793.  
  6794.     {constant for transaction IDs}
  6795.     kAnyTransactionID                                 = 0;                    {the Apple event is not }
  6796.                                                         { part of a transaction}
  6797.  
  6798.     {constants for timeout durations}
  6799.     kAEDefaultTimeout                                = -1;                    {use default timeout value}
  6800.     kNoTimeOut                                = -2;                    {never time out}
  6801.  
  6802.     {constants for the dispatcher parameter of AEResumeTheCurrentEvent}
  6803.     kAENoDispatch                                = 0;                    {don't redispatch the Apple event}
  6804.     kAEUseStandardDispatch                                = -1;                    {redispatch the Apple event }
  6805.                                                         { by using its entry in the }
  6806.                                                         { Apple event dispatch table}
  6807. Data Types
  6808.  
  6809. TYPE
  6810.     AEEventClass = 
  6811.         PACKED ARRAY[1..4] OF Char;                                                    {event class for a high-level }
  6812.                                                             { event}
  6813.     AEEventID = 
  6814.         PACKED ARRAY[1..4] OF Char;                                                    {event ID for a high-level }
  6815.                                                             { event}
  6816.  
  6817.     AEKeyword = 
  6818.         PACKED ARRAY[1..4] OF Char;                                                    {keyword for a descriptor }
  6819.                                                             { record}
  6820.  
  6821.     DescType                                    = ResType;                    {descriptor type}
  6822.  
  6823.     AEDesc =                                                         {descriptor record}
  6824.     RECORD        
  6825.         descriptorType:                                 DescType;                    {type of data being passed}
  6826.         dataHandle:                                 Handle;                    {handle to data being passed}
  6827.     END;
  6828.  
  6829.     AEKeyDesc =                                                         {keyword-specified }
  6830.     RECORD                                                        { descriptor record}
  6831.         descKey:                                AEKeyword;                    {keyword}
  6832.         descContent:                                AEDesc    ;                {descriptor record}
  6833.     END;
  6834.  
  6835.     AEAddressDesc                                    = AEDesc;                    {address descriptor record}
  6836.  
  6837.     AEDescList                                    = AEDesc;                    {list of descriptor records}
  6838.  
  6839.     AERecord                                    = AEDescList;                    {list of keyword-specified }
  6840.                                                             { descriptor records}
  6841.  
  6842.     AppleEvent                                    = AERecord;                    {list of attributes and }
  6843.                                                             { parameters necessary for }
  6844.                                                             { an Apple event}
  6845.     AESendMode                                    = LongInt;                    {flags that determine how }
  6846.                                                             { an Apple event is sent}
  6847.  
  6848.     AESendPriority                                    = Integer;                    {send priority of an Apple }
  6849.                                                             { event}
  6850.     AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal,
  6851.                                                    kAEInteractWithAll);                            {what processes may }
  6852.                                                             { interact with the user}
  6853.  
  6854.     AEEventSource = (kAEUnknownSource, kAEDirectCall, kAESameProcess,
  6855.                                            kAELocalProcess, kAERemoteProcess);
  6856.                                                             {the source of an Apple }
  6857.                                                             { event}
  6858.  
  6859.     AEArrayType = (kAEDataArray, kAEPackedArray, kAEHandleArray, 
  6860.                                     kAEDescArray, kAEKeyDescArray);
  6861.                                                             {type of an Apple event array}
  6862.     AEArrayData = 
  6863.     RECORD                                                        {data for an Apple event array}
  6864.         CASE AEArrayType OF
  6865.         kAEDataArray:
  6866.             (AEDataArray:     ARRAY[0..0] OF Integer);
  6867.         kAEPackedArray:
  6868.             (AEPackedArray:     PACKED ARRAY[0..0] OF Char);
  6869.         kAEHandleArray:
  6870.             (AEHandleArray:     ARRAY[0..0] OF Handle);
  6871.         kAEDescArray:
  6872.             (AEDescArray:     ARRAY[0..0] OF AEDesc);
  6873.         kAEKeyDescArray:
  6874.             (AEKeyDescArray:     ARRAY[0..0] OF AEKeyDesc);
  6875.     END;
  6876.     
  6877.     AEArrayDataPointer = ^AEArrayData;
  6878.  
  6879.     EventHandlerProcPtr = ProcPtr;                                                        {pointer to an Apple event }
  6880.                                                             { handler}
  6881.     IdleProcPtr = ProcPtr;                                                        {pointer to an application's }
  6882.                                                             { idle function}
  6883.     EventFilterProcPtr = ProcPtr;                                                        {pointer to an application's }
  6884.                                                             { filter function}
  6885. Routines for Responding to Apple Events
  6886.  
  6887. Creating and Managing the Apple Event Dispatch Tables
  6888. FUNCTION AEInstallEventHandler
  6889. (theAEEventClass: AEEventClass; 
  6890. theAEEventID: AEEventID; 
  6891. handler: EventHandlerProcPtr; 
  6892. handlerRefcon: LongInt; 
  6893. isSysHandler: Boolean): OSErr;
  6894. FUNCTION AEGetEventHandler    (theAEEventClass: AEEventClass; 
  6895. theAEEventID: AEEventID; 
  6896. VAR handler: EventHandlerProcPtr; 
  6897. VAR handlerRefcon: LongInt; 
  6898. isSysHandler: Boolean): OSErr;
  6899. FUNCTION AERemoveEventHandler
  6900. (theAEEventClass: AEEventClass; theAEEventID: AEEventID; handler: EventHandlerProcPtr; isSysHandler: Boolean): OSErr;
  6901. Dispatching Apple Events
  6902. FUNCTION AEProcessAppleEvent
  6903. (theEventRecord: EventRecord): OSErr;
  6904. Getting Data or Descriptor Records Out of Apple Event Parameters and Attributes
  6905. FUNCTION AEGetParamPtr    (theAppleEvent: AppleEvent; 
  6906. theAEKeyword: AEKeyword; 
  6907. desiredType: DescType; 
  6908. VAR typeCode: DescType; 
  6909. dataPtr: Ptr; maximumSize: Size; 
  6910. VAR actualSize: Size): OSErr;
  6911. FUNCTION AEGetParamDesc    (theAppleEvent: AppleEvent; 
  6912. theAEKeyword: AEKeyword; desiredType: DescType; 
  6913. VAR result: AEDesc): OSErr;
  6914. FUNCTION AEGetAttributePtr    (theAppleEvent: AppleEvent; 
  6915. theAEKeyword: AEKeyword; desiredType: DescType; 
  6916. VAR typeCode: DescType; 
  6917. dataPtr: Ptr; maximumSize: Size; 
  6918. VAR actualSize: Size): OSErr;
  6919. FUNCTION AEGetAttributeDesc    (theAppleEvent: AppleEvent; 
  6920. theAEKeyword: AEKeyword; desiredType: DescType; 
  6921. VAR result: AEDesc): OSErr;
  6922. Counting the Items in Descriptor Lists
  6923. FUNCTION AECountItems    (theAEDescList: AEDescList; 
  6924. VAR theCount: LongInt): OSErr;
  6925. Getting Items From Descriptor Lists
  6926. FUNCTION AEGetNthPtr    (theAEDescList: AEDescList; index: LongInt; desiredType: DescType; 
  6927. VAR theAEKeyword: AEKeyword; 
  6928. VAR typeCode: DescType; dataPtr: Ptr; maximumSize: Size; 
  6929. VAR actualSize: Size): OSErr;
  6930. FUNCTION AEGetNthDesc    (theAEDescList: AEDescList; index: LongInt; 
  6931. desiredType: DescType; 
  6932. VAR theAEKeyword: AEKeyword; 
  6933. VAR result: AEDesc): OSErr;
  6934. FUNCTION AEGetArray    (theAEDescList: AEDescList; 
  6935. arrayType: AEArrayType; 
  6936. arrayPtr: AEArrayDataPointer; 
  6937. maximumSize: Size; 
  6938. VAR itemType: DescType; VAR itemSize: Size; 
  6939. VAR itemCount: LongInt): OSErr;
  6940. Getting Data and Keyword-Specified Descriptor Records Out of AE Records
  6941. FUNCTION AEGetKeyPtr    (theAERecord: AERecord; 
  6942. theAEKeyword: AEKeyword; 
  6943. desiredType: DescType; VAR typeCode: DescType; dataPtr: Ptr; maximumSize: Size; 
  6944. VAR actualSize: Size): OSErr;
  6945. FUNCTION AEGetKeyDesc    (theAERecord: AERecord; 
  6946. theAEKeyword: AEKeyword; 
  6947. desiredType: DescType; 
  6948. VAR result: AEDesc): OSErr;
  6949. Requesting User Interaction
  6950. FUNCTION AESetInteractionAllowed
  6951. (level: AEInteractAllowed): OSErr;
  6952. FUNCTION AEGetInteractionAllowed
  6953. (VAR level: AEInteractAllowed): OSErr;
  6954. FUNCTION AEInteractWithUser    (timeOutInTicks: LongInt; nmReqPtr: NMRecPtr; idleProc: IdleProcPtr): OSErr;
  6955. Requesting More Time to Respond to Apple Events
  6956. FUNCTION AEResetTimer    (reply: AppleEvent): OSErr;
  6957. Suspending and Resuming Apple Event Handling
  6958. FUNCTION AESuspendTheCurrentEvent    
  6959. (theAppleEvent: AppleEvent): OSErr;
  6960. FUNCTION AEResumeTheCurrentEvent
  6961. (theAppleEvent, reply: AppleEvent;             
  6962. dispatcher: EventHandlerProcPtr; handlerRefcon: LongInt): OSErr;
  6963. FUNCTION AESetTheCurrentEvent
  6964. (theAppleEvent: AppleEvent): OSErr;
  6965. FUNCTION AEGetTheCurrentEvent
  6966. (VAR theAppleEvent: AppleEvent): OSErr;
  6967. Getting the Sizes and Descriptor Types of Descriptor Records
  6968. FUNCTION AESizeOfNthItem    (theAEDescList: AEDescList; index: LongInt; 
  6969. VAR typeCode: DescType; 
  6970. VAR dataSize: Size): OSErr;
  6971. FUNCTION AESizeOfKeyDesc    (theAERecord: AERecord; 
  6972. theAEKeyword: AEKeyword; 
  6973. VAR typeCode: DescType; 
  6974. VAR dataSize: Size): OSErr;
  6975. FUNCTION AESizeOfParam    (theAppleEvent: AppleEvent; 
  6976. theAEKeyword: AEKeyword; 
  6977. VAR typeCode: DescType; 
  6978. VAR dataSize: Size): OSErr;
  6979. FUNCTION AESizeOfAttribute    (theAppleEvent: AppleEvent; 
  6980. theAEKeyword: AEKeyword; 
  6981. VAR typeCode: DescType; 
  6982. VAR dataSize: Size): OSErr;
  6983. Deleting Descriptor Records
  6984. FUNCTION AEDeleteItem    (theAEDescList: AEDescList; 
  6985. index: LongInt): OSErr;
  6986. FUNCTION AEDeleteKeyDesc    (theAERecord: AERecord; 
  6987. theAEKeyword: AEKeyword): OSErr;
  6988. FUNCTION AEDeleteParam    (theAppleEvent: AppleEvent; 
  6989. theAEKeyword: AEKeyword): OSErr;
  6990. Deallocating Memory for Descriptor Records
  6991. FUNCTION AEDisposeDesc    (VAR theAEDesc: AEDesc): OSErr;
  6992. Coercing Descriptor Types
  6993. FUNCTION AECoercePtr    (typeCode: DescType; dataPtr: Ptr; 
  6994. dataSize: Size; toType: DescType; 
  6995. VAR result: AEDesc): OSErr;
  6996. FUNCTION AECoerceDesc    (theAEDesc: AEDesc; toType: DescType; 
  6997. VAR result: AEDesc): OSErr;
  6998. Creating and Managing the Coercion Handler Dispatch Tables
  6999. FUNCTION AEInstallCoercionHandler
  7000. (fromType: DescType; toType: DescType; 
  7001. handler: ProcPtr; handlerRefcon: LongInt; fromTypeIsDesc: Boolean; 
  7002. isSysHandler: Boolean): OSErr;
  7003. FUNCTION AEGetCoercionHandler
  7004. (fromType: DescType; toType: DescType; 
  7005. VAR handler: ProcPtr; 
  7006. VAR handlerRefcon: LongInt; 
  7007. VAR fromTypeIsDesc: Boolean; 
  7008. isSysHandler: Boolean): OSErr;
  7009. FUNCTION AERemoveCoercionHandler
  7010. (fromType: DescType; toType: DescType; 
  7011. handler: ProcPtr; 
  7012. isSysHandler: Boolean): OSErr;
  7013. Creating and Managing the Special Handler Dispatch Tables
  7014. FUNCTION AEInstallSpecialHandler
  7015. (functionClass: AEKeyword; handler: ProcPtr; isSysHandler: Boolean): OSErr;
  7016. FUNCTION AEGetSpecialHandler
  7017. (functionClass: AEKeyword; 
  7018. VAR handler: ProcPtr; 
  7019. isSysHandler: Boolean): OSErr;
  7020. FUNCTION AERemoveSpecialHandler
  7021. (functionClass: AEKeyword; handler: ProcPtr; isSysHandler: Boolean): OSErr;
  7022. Getting Information About the Apple Event Manager
  7023. {available only in version 1.01 and later versions of Apple Event Manager}
  7024. FUNCTION AEManagerInfo     (keyword: AEKeyword; 
  7025. VAR result: LongInt): OSErr;
  7026. Application-Defined Routines
  7027.  
  7028. FUNCTION MyEventHandler    (theAppleEvent: AppleEvent; reply: AppleEvent; handlerRefcon: LongInt): OSErr; 
  7029. FUNCTION MyCoercePtr    (typeCode: DescType; dataPtr: Ptr; 
  7030. dataSize: Size; toType: DescType; handlerRefcon: LongInt; 
  7031. VAR result: AEDesc): OSErr; 
  7032. FUNCTION MyCoerceDesc    (theAEDesc: AEDesc; toType: DescType; handlerRefcon: LongInt; 
  7033. VAR result: AEDesc): OSErr;
  7034. C Summary
  7035.  
  7036. Constants
  7037.  
  7038. enum {
  7039.         #define gestaltAppleEventsAttr                                      'evnt'                /*selector for Apple events*/
  7040.         gestaltAppleEventsPresent                                             = 0         /*if this bit is set, then */
  7041.                                                             /* Apple Event Manager is */
  7042. };                                                            /* available*/
  7043.  
  7044.         /*Apple event descriptor types*/
  7045. enum        {
  7046.         typeBoolean                                = 'bool',                    /*1-byte Boolean value*/
  7047.         typeChar                                = 'TEXT',                    /*unterminated string*/
  7048.         typeSMInt                                = 'shor',                    /*16-bit integer*/
  7049.         typeInteger                                = 'long',                    /*32-bit integer*/
  7050.         typeSMFloat                                = 'sing',                    /*SANE single*/
  7051.         typeFloat                                = 'doub',                    /*SANE double*/
  7052.         typeLongInteger                                = 'long',                    /*32-bit integer*/
  7053.         typeShortInteger                                = 'shor',                    /*16-bit integer*/
  7054.         typeLongFloat                                = 'doub',                    /*SANE double*/
  7055.         typeShortFloat                                = 'sing',                    /*SANE single*/
  7056.         typeExtended                                = 'exte',                    /*SANE extended*/
  7057.         typeComp                                = 'comp',                    /*SANE comp*/
  7058.         typeMagnitude                                = 'magn',                    /*unsigned 32-bit integer*/
  7059.         typeAEList                                = 'list',                    /*list of descriptor records*/
  7060.         typeAERecord                                = 'reco',                    /*list of keyword-specified */
  7061.                                                             /* descriptor records*/
  7062.         typeAppleEvent                                = 'aevt',                    /*Apple event record*/
  7063.         typeTrue                                = 'true',                    /*TRUE Boolean value*/
  7064.         typeFalse                                = 'fals',                    /*FALSE Boolean value*/
  7065.         typeAlias                                = 'alis',                    /*alias record*/
  7066.         typeEnumerated                                = 'enum'                    /*enumerated data*/
  7067. };
  7068.  
  7069. enum {
  7070.         typeType                                = 'type',                    /*four-character code for */
  7071.                                                             /* event class or event ID*/
  7072.         typeAppParameters                                = 'appa',                    /*Process Manager launch */
  7073.                                                             /* parameters*/
  7074.         typeProperty                                = 'prop',                    /*Apple event property*/
  7075.         typeFSS                                = 'fss ',                    /*file system specification*/
  7076.         typeKeyword                                = 'keyw',                    /*Apple event keyword*/
  7077.  
  7078.         typeSectionH                                = 'sect',                    /*handle to a section record*/
  7079.         typeWildCard                                = '****',                    /*matches any type*/
  7080.         typeApplSignature                                = 'sign',                    /*application signature*/
  7081.         typeSessionID                                = 'ssid',                    /*session ID*/
  7082.         typeTargetID                                = 'targ',                    /*target ID record*/
  7083.         typeProcessSerialNumber                                = 'psn ',                    /*process serial number*/
  7084.         typeNull                                = 'null'                    /*NULL or nonexistent data*/
  7085. };
  7086.  
  7087.         /*keywords for Apple event parameters*/
  7088. enum     {
  7089.         keyDirectObject                                = '----',                    /*direct parameter*/
  7090.         keyErrorNumber                                = 'errn',                    /*error number parameter*/
  7091.         keyErrorString                                = 'errs',                    /*error string parameter*/
  7092.         keyProcessSerialNumber                                = 'psn '                    /*process serial number param*/
  7093. };
  7094.  
  7095.         /*keywords for Apple event attributes*/
  7096. enum     {
  7097.         keyTransactionIDAttr                                = 'tran',                    /*transaction ID*/
  7098.         keyReturnIDAttr                                = 'rtid',                    /*return ID*/
  7099.         keyEventClassAttr                                 = 'evcl',                    /*event class*/
  7100.         keyEventIDAttr                                = 'evid',                    /*event ID*/
  7101.         keyAddressAttr                                = 'addr',                    /*address of target or */
  7102.                                                             /* client application*/
  7103.         keyOptionalKeywordAttr                                = 'optk',                    /*list of optional parameters */
  7104.                                                             /* for the Apple event*/
  7105.         keyTimeoutAttr                                = 'timo',                    /*number of ticks the client */
  7106.                                                             /* will wait*/
  7107.         keyInteractLevelAttr                                 = 'inte',                    /*settings to allow Apple */
  7108.                                                             /* Event Mgr to bring */                    
  7109.                                                             /* server to foreground*/
  7110.         keyEventSourceAttr                                = 'esrc',                    /*nature of source */
  7111.                                                             /* application*/
  7112.         keyMissedKeywordAttr                                = 'miss',                    /*first required parameter */
  7113.                                                             /* remaining in an Apple */
  7114.                                                             /* event*/
  7115.         keyOriginalAddressAttr                                = 'from'                    /*address of original source; */
  7116.                                                             /* available only in version */ 
  7117.                                                             /* 1.01 and later versions of */
  7118.                                                             /* the Apple Event Manager*/
  7119. };
  7120.         
  7121.         /*keywords for special handlers*/
  7122. enum     {
  7123.         keyPreDispatch                                = 'phac',                    /*identifies a handler */
  7124.                                                             /* routine that is called */
  7125.                                                             /* immediately before the */
  7126.                                                             /* Apple Event Manager */
  7127.                                                             /* dispatches an Apple event*/
  7128.         keySelectProc                                = 'selh',                     /*selector used with */
  7129.                                                             /* AERemoveSpecialHandler to */
  7130.                                                             /* disable the OSL*/
  7131.  
  7132.         /*keywords for use with AEManagerInfo, available only in version */
  7133.         /* 1.0.1 and later versions of the Apple Event Manager*/
  7134.         keyAERecorderCount                                 = 'recr',                    /*keyword for recording info*/
  7135.         keyAEVersion                                 = 'vers',                    /*keyword for version info*/
  7136.  
  7137.         /*event class*/
  7138.         kCoreEventClass                                = 'aevt'                    /*event class for required */
  7139.                                                             /* Apple events*/
  7140. };
  7141.  
  7142.  
  7143.         /*event IDs for required Apple events*/
  7144. enum {
  7145.         kAEOpenApplication                                = 'oapp',                    /*event ID for Open */
  7146.                                                             /* Application event*/
  7147.         kAEOpenDocuments                                = 'odoc',                    /*event ID for Open */
  7148.                                                             /* Documents event*/
  7149.  
  7150.         kAEPrintDocuments                                = 'pdoc',                    /*event ID for Print */
  7151.                                                             /* Documents event*/
  7152.         kAEQuitApplication                                = 'quit',                    /*event ID for Quit */
  7153.                                                             /* Application event*/
  7154.         kAEAnswer                                = 'ansr',                    /*event ID for Apple event */
  7155.                                                             /* replies*/
  7156.         kAEApplicationDied                                = 'obit'                    /*event ID for Application */
  7157.                                                             /* Died event*/
  7158. };
  7159.         /*constants for setting the sendMode parameter of AESend*/
  7160. enum {
  7161.         kAENoReply                                = 0x00000001,                    /*client doesn't want reply*/
  7162.         kAEQueueReply                                = 0x00000002,                    /*client wants server to */
  7163.                                                             /* reply in event queue*/
  7164.         kAEWaitReply                                = 0x00000003,                    /*client wants a reply and */
  7165.                                                             /* will give up processor*/
  7166.         kAENeverInteract                                = 0x00000010,                    /*server application should */
  7167.                                                             /* not interact with user */
  7168.                                                             /* for this Apple event*/
  7169.         kAECanInteract                                = 0x00000020,                    /*server may interact with */
  7170.                                                             /* user for this Apple event */
  7171.                                                             /* to supply information*/
  7172.         kAEAlwaysInteract                                = 0x00000030,                    /*server may interact with */
  7173.                                                             /* user for this Apple event */
  7174.                                                             /* even if no information */
  7175.                                                             /* is required*/
  7176.         kAECanSwitchLayer                                = 0x00000040,                    /*server should come */
  7177.                                                             /* directly to foreground */
  7178.                                                             /* when appropriate*/
  7179.         kAEDontReconnect                                = 0x00000080,                    /*don't reconnect if there */
  7180.                                                             /* is a PPC session closed */
  7181.                                                             /* error*/
  7182.         kAEWantReceipt                                = nReturnReceipt, /*client wants return */
  7183.                                                             /* receipt*/
  7184.         kAEDontRecord                                = 0x00001000,                    /*don't record this event*/
  7185.         kAEDontExecute                                = 0x00002000,                    /*don't excecute this event*/
  7186.         /*constants for setting the sendPriority parameter of AESend*/
  7187.         kAENormalPriority                                = 0x00000000,                    /*post message at end of */
  7188.                                                             /* event queue*/
  7189.         kAEHighPriority                                = nAttnMsg                    /*post message at front of */
  7190.                                                             /* event queue*/
  7191. };
  7192.  
  7193.         /*event IDs for recording events; available only in version 1.01 and */
  7194.         /* later versions of the Apple Event Manager*/
  7195. enum {
  7196.         kAEStartRecording                                = 'reca'        ,            /*event ID for Start */
  7197.                                                             /* Recording event*/
  7198.         kAEStopRecording                                = 'recc',                    /*event ID for Stop */
  7199.                                                             /* Recording event*/
  7200.         kAENotifyStartRecording                                = 'rec1',                    /*event ID for Recording On*/
  7201.                                                             /* event*/
  7202.         kAENotifyStopRecording                                = 'rec0',                    /*event ID for Recording Off */
  7203.                                                             /* event*/
  7204.         kAENotifyRecording                                = 'recr'                    /*event ID for Receive */
  7205.                                                             /* Recordable Event event*/
  7206. };
  7207. enum {
  7208.         /*constant for the returnID parameter of AECreateAppleEvent*/
  7209.         kAutoGenerateReturnID                                = -1,                    /*tells Apple Event Manager */
  7210.                                                             /* to generate a unique */
  7211.                                                             /* return ID*/
  7212.  
  7213.         /*constant for transaction IDs*/
  7214.         kAnyTransactionID                                 = 0,                    /*the Apple event is not */
  7215.                                                             /* part of a transaction*/
  7216.  
  7217.         /*constants for timeout durations*/
  7218.         kAEDefaultTimeout                                = -1,                    /*use default timeout value*/
  7219.         kNoTimeOut                                = -2    ,                /*never time out*/
  7220.  
  7221.         /*constants for the dispatcher parameter of AEResumeTheCurrentEvent*/
  7222.         kAENoDispatch                                = 0,                    /*don't redispatch the */
  7223.                                                             /* Apple event*/
  7224.         kAEUseStandardDispatch                                = -1                /*redispatch the Apple event */
  7225.                                                             /* by using its entry in the */
  7226.                                                             /* Apple event dispatch table*/
  7227. };
  7228. Data Types
  7229.  
  7230. typedef unsigned long AEEventClass;                                                            /*event class for a */
  7231.                                                             /* high-level event*/
  7232. typedef unsigned long AEEventID;                                                            /*event ID for a high-level */
  7233.                                                             /* event*/
  7234.  
  7235. typedef unsigned long AEKeyword;                                                            /*keyword for a descriptor */
  7236.                                                             /* record*/
  7237. typedef ResType DescType                                ;                            /*descriptor type*/
  7238.  
  7239. struct AEDesc {                                                             /*descriptor record*/
  7240.     DescType descriptorType;                                                         /*type of data being passed*/
  7241.     Handle dataHandle;                                                        /*handle to data being passed*/
  7242. };
  7243. typedef struct AEDesc AEDesc;
  7244.  
  7245. struct AEKeyDesc {                                                             /*keyword-specified */
  7246.                                                             /* descriptor record*/
  7247.     AEKeyword descKey;                                                        /*keyword*/
  7248.     AEDesc descContent;                                                        /*descriptor record*/
  7249. };
  7250. typedef struct AEKeyDesc AEKeyDesc;
  7251.  
  7252. typedef AEDesc AEAddressDesc;                                                            /*address descriptor record*/
  7253. typedef AEDesc AEDescList;                                                            /*list of descriptor records*/
  7254. typedef AEDescList AERecord;                                                            /*list of keyword-specified */
  7255.                                                             /* descriptor records*/
  7256. typedef AERecord AppleEvent;                                                            /*list of attributes and */
  7257.                                                             /* parameters necessary for */
  7258.                                                             /* an Apple event*/
  7259. typedef long AESendMode;                                                            /*flags that determine how */
  7260.                                                             /* an Apple event is sent*/
  7261.  
  7262. typedef short AESendPriority;                                                            /*send priority of an Apple */
  7263.                                                             /* event*/
  7264.  
  7265. enum { kAEInteractWithSelf, kAEInteractWithLocal,
  7266.          kAEInteractWithAll };                                                    /*what processes may */
  7267. typedef unsigned char AEInteractAllowed;                                                            /* interact with the user*/
  7268.  
  7269.  
  7270.  
  7271. enum { kAEUnknownSource, kAEDirectCall, kAESameProcess,             kAELocalProcess, 
  7272.          kAERemoteProcess };                                                    /*the source of an Apple */
  7273. typedef unsigned char AEEventSource;                                                            /* event*/
  7274. enum { kAEDataArray, kAEPackedArray, kAEHandleArray, 
  7275.        kAEDescArray, kAEKeyDescArray };                                                            /*type of an Apple event */
  7276. typedef unsigned char AEArrayType;                                                            /* array*/
  7277.  
  7278. union AEArrayData {                                                                 /*data for an Apple event */
  7279.     short                kAEDataArray[1];                                            /* array*/
  7280.     char                kAEPackedArray[1];
  7281.     Handle                 kAEHandleArray[1];
  7282.     AEDesc                 kAEDescArray[1];                        
  7283.     AEKeyDesc                kAEKeyDescArray[1];
  7284. };
  7285. typedef union AEArrayData AEArrayData;
  7286.  
  7287. typedef AEArrayData *AEArrayDataPointer;
  7288.  
  7289. typedef ProcPtr EventHandlerProcPtr;                                                            /*pointer to an Apple event */
  7290.                                                             /* handler*/
  7291. typedef ProcPtr IdleProcPtr;                                                            /*pointer to an application's */
  7292.                                                             /* idle function*/
  7293. typedef ProcPtr EventFilterProcPtr;                                                            /*pointer to an application's */
  7294.                                                             /* filter function*/
  7295. Routines for Responding to Apple Events
  7296.  
  7297. Creating and Managing the Apple Event Dispatch Tables
  7298. pascal OSErr AEInstallEventHandler
  7299. (AEEventClass theAEEventClass, 
  7300. AEEventID theAEEventID,
  7301. EventHandlerProcPtr handler,
  7302. long handlerRefcon, Boolean isSysHandler);
  7303. pascal OSErr AEGetEventHandler
  7304. (AEEventClass theAEEventClass,
  7305. AEEventID theAEEventID,
  7306. EventHandlerProcPtr *handler, 
  7307. long *handlerRefcon, Boolean isSysHandler);
  7308. pascal OSErr AERemoveEventHandler
  7309. (AEEventClass theAEEventClass,
  7310. AEEventID theAEEventID,
  7311. EventHandlerProcPtr handler, 
  7312. Boolean isSysHandler);
  7313. Dispatching Apple Events
  7314. pascal  OSErr  AEProcessAppleEvent     
  7315.     (const EventRecord *theEventRecord);
  7316. Getting Data or Descriptor Records Out of Apple Event Parameters and Attributes
  7317. pascal OSErr AEGetParamPtr    (const AppleEvent *theAppleEvent, 
  7318. AEKeyword theAEKeyword, DescType desiredType, DescType *typeCode, void* dataPtr, 
  7319. Size maximumSize, Size *actualSize);
  7320. pascal OSErr AEGetParamDesc    (const AppleEvent *theAppleEvent, 
  7321. AEKeyword theAEKeyword, DescType desiredType, 
  7322. AEDesc *result);
  7323. pascal OSErr AEGetAttributePtr
  7324. (const AppleEvent *theAppleEvent, 
  7325. AEKeyword theAEKeyword, DescType desiredType, 
  7326. DescType *typeCode, void* dataPtr,
  7327. Size maximumSize, Size *actualSize); 
  7328. pascal OSErr AEGetAttributeDesc
  7329. (const AppleEvent *theAppleEvent, 
  7330. AEKeyword theAEKeyword, DescType desiredType, 
  7331. AEDesc *result);
  7332. Counting the Items in Descriptor Lists
  7333. pascal OSErr AECountItems    (const AEDescList *theAEDescList, 
  7334. long *theCount);
  7335. Getting Items From Descriptor Lists
  7336. pascal OSErr AEGetNthPtr    (const AEDescList *theAEDescList, long index, DescType desiredType, AEKeyword *theAEKeyword, 
  7337. DescType *typeCode, void* dataPtr,
  7338. Size maximumSize, Size *actualSize);
  7339. pascal OSErr AEGetNthDesc    (const AEDescList *theAEDescList, long index, 
  7340. DescType desiredType, AEKeyword *theAEKeyword, 
  7341. AEDesc *result);
  7342. pascal OSErr AEGetArray    (const AEDescList *theAEDescList, 
  7343. AEArrayType arrayType, 
  7344. AEArrayDataPointer arrayPtr, Size maximumSize, DescType *itemType, Size *itemSize, 
  7345. long *itemCount);
  7346. Getting Data and Keyword-Specified Descriptor Records Out of AE Records
  7347. pascal OSErr AEGetKeyPtr    (const AERecord *theAERecord, 
  7348. AEKeyword theAEKeyword, DescType desiredType, DescType *typeCode, void* dataPtr, 
  7349. Size maximumSize, Size *actualSize);
  7350. pascal OSErr AEGetKeyDesc    (const AERecord *theAERecord, 
  7351. AEKeyword theAEKeyword, DescType desiredType, AEDesc *result);
  7352. Requesting User Interaction
  7353. pascal OSErr AESetInteractionAllowed
  7354. (AEInteractAllowed level);
  7355. pascal OSErr AEGetInteractionAllowed
  7356. (AEInteractAllowed *level);
  7357. pascal OSErr AEInteractWithUser
  7358. (long timeOutInTicks, NMRecPtr nmReqPtr, IdleProcPtr idleProc);
  7359. Requesting More Time to Respond to Apple Events
  7360. pascal OSErr AEResetTimer    (const AppleEvent *reply);
  7361. Suspending and Resuming Apple Event Handling
  7362. pascal OSErr AESuspendTheCurrentEvent
  7363. (const AppleEvent *theAppleEvent);
  7364. pascal OSErr AEResumeTheCurrentEvent
  7365. (const AppleEvent *theAppleEvent,
  7366. const AppleEvent *reply,
  7367. EventHandlerProcPtr dispatcher,
  7368. long handlerRefcon);
  7369. pascal OSErr AESetTheCurrentEvent
  7370. (const AppleEvent *theAppleEvent);
  7371. pascal OSErr AEGetTheCurrentEvent
  7372. (AppleEvent *theAppleEvent);
  7373. Getting the Sizes and Descriptor Types of Descriptor Records
  7374. pascal OSErr AESizeOfNthItem
  7375. (const AEDescList *theAEDescList, long index, 
  7376. DescType *typeCode, Size *dataSize);
  7377. pascal OSErr AESizeOfKeyDesc
  7378. (const AERecord *theAERecord, 
  7379. AEKeyword theAEKeyword, DescType *typeCode, 
  7380. Size *dataSize);
  7381. pascal OSErr AESizeOfParam    (const AppleEvent *theAppleEvent, 
  7382. AEKeyword theAEKeyword, DescType *typeCode, Size *dataSize);
  7383. pascal OSErr AESizeOfAttribute
  7384. (const AppleEvent *theAppleEvent, 
  7385. AEKeyword theAEKeyword, DescType *typeCode, Size *dataSize);
  7386. Deleting Descriptor Records
  7387. pascal OSErr AEDeleteItem    (const AEDescList *theAEDescList, long index);
  7388. pascal OSErr AEDeleteKeyDesc
  7389. (const AERecord *theAERecord, 
  7390. AEKeyword theAEKeyword);
  7391. pascal OSErr AEDeleteParam    (const AppleEvent *theAppleEvent, 
  7392. AEKeyword theAEKeyword);
  7393. Deallocating Memory for Descriptor Records
  7394. pascal OSErr AEDisposeDesc    (AEDesc *theAEDesc);
  7395. Coercing Descriptor Types
  7396. pascal OSErr AECoercePtr    (DescType typeCode, const void* dataPtr, 
  7397. Size dataSize, DescType toType, 
  7398. AEDesc *result);
  7399. pascal OSErr AECoerceDesc    (const AEDesc *theAEDesc, DescType toType, 
  7400. AEDesc *result);
  7401. Creating and Managing the Coercion Handler Dispatch Tables
  7402. pascal OSErr AEInstallCoercionHandler
  7403. (DescType fromType, DescType toType, 
  7404. ProcPtr handler, long handlerRefcon, 
  7405. Boolean fromTypeIsDesc, Boolean isSysHandler);
  7406. pascal OSErr AEGetCoercionHandler
  7407. (DescType fromType, DescType toType, 
  7408. ProcPtr *handler, long *handlerRefcon, 
  7409. Boolean *fromTypeIsDesc, 
  7410. Boolean isSysHandler);
  7411. pascal OSErr AERemoveCoercionHandler
  7412. (DescType fromType, DescType toType, 
  7413. ProcPtr handler, Boolean isSysHandler);
  7414. Creating and Managing the Special Handler Dispatch Tables
  7415. pascal OSErr AEInstallSpecialHandler
  7416. (AEKeyword functionClass, ProcPtr handler, Boolean isSysHandler);
  7417. pascal OSErr AEGetSpecialHandler
  7418. (AEKeyword functionClass, ProcPtr *handler, 
  7419. Boolean isSysHandler);
  7420. pascal OSErr AERemoveSpecialHandler
  7421. (AEKeyword functionClass, ProcPtr handler, Boolean isSysHandler);
  7422. Getting Information About the Apple Event Manager
  7423. /*available only in version 1.01 and later versions of Apple Event Manager*/
  7424. pascal OSErr AEManagerInfo     (AEKeyword keyword, long *result);
  7425. Application-Defined Routines
  7426.  
  7427. pascal OSErr MyEventHandler    (const AppleEvent *theAppleEvent, 
  7428. const AppleEvent *reply, long handlerRefcon); 
  7429. pascal OSErr MyCoercePtr    (DescType typeCode, const void* dataPtr, 
  7430. Size dataSize, DescType toType, 
  7431. long handlerRefcon, AEDesc *result); 
  7432. pascal OSErr MyCoerceDesc    (const AEDesc *theAEDesc, DescType toType, long handlerRefcon, AEDesc *result);
  7433. Assembly-Language Summary
  7434.  
  7435. Trap Macros
  7436.  
  7437. Trap Macros Requiring Routine Selectors
  7438. _Pack8
  7439. Selector    Routine    
  7440. $011E    AESetInteractionAllowed    
  7441. $0204    AEDisposeDesc    
  7442. $0219    AEResetTimer    
  7443. $021A    AEGetTheCurrentEvent    
  7444. $021B    AEProcessAppleEvent    
  7445. $021D    AEGetInteractionAllowed    
  7446. $022B    AESuspendTheCurrentEvent    
  7447. $022C    AESetTheCurrentEvent    
  7448. $0407    AECountItems    
  7449. $040E    AEDeleteItem    
  7450. $0413    AEDeleteKeyDesc    
  7451. $0413    AEDeleteParam    
  7452. $0441    AEManagerInfo    
  7453. $0500    AEInstallSpecialHandler    
  7454. $0501    AERemoveSpecialHandler    
  7455. $052D    AEGetSpecialHandler    
  7456. $0603    AECoerceDesc    
  7457. $061C    AEInteractWithUser    
  7458. $0720    AERemoveEventHandler    
  7459. $0723    AERemoveCoercionHandler    
  7460. $0812    AEGetKeyDesc    
  7461. $0812    AEGetParamDesc    
  7462. $0818    AEResumeTheCurrentEvent    
  7463. $0826    AEGetAttributeDesc    
  7464. $0828    AESizeOfAttribute    
  7465. $0829    AESizeOfKeyDesc    
  7466. $0829    AESizeOfParam    
  7467. $082A    AESizeOfNthItem    
  7468. $091F    AEInstallEventHandler    
  7469. $0921    AEGetEventHandler    
  7470. $0A02    AECoercePtr    
  7471. $0A22    AEInstallCoercionHandler    
  7472. $0A0B    AEGetNthDesc    
  7473. $0B24    AEGetCoercionHandler    
  7474. $0D0C    AEGetArray    
  7475. $0E11    AEGetKeyPtr    
  7476. $0E11    AEGetParamPtr    
  7477. $0E15    AEGetAttributePtr    
  7478. $100A    AEGetNthPtr    
  7479.  
  7480. Result CodesnoErr    0    No error    
  7481. paramErr    –50    Parameter error (for example, value of handler pointer is NIL or odd)    
  7482. eLenErr    –92    Buffer too big to send    
  7483. memFullErr    –108    Not enough room in heap zone    
  7484. userCanceledErr    –128    User canceled an operation    
  7485. procNotFound    –600    No eligible process with specified process serial number    
  7486. bufferIsSmall    –607    Buffer is too small    
  7487. noOutstandingHLE    –608    No outstanding high-level event    
  7488. connectionInvalid    –609    Nonexistent signature or session ID    
  7489. noUserInteractionAllowed    –610    Background application sends event requiring authentication    
  7490. noPortErr    –903    Client hasn’t set 'SIZE' resource to indicate awareness of high-level events    
  7491. destPortErr    –906    Server hasn’t set 'SIZE' resource to indicate awareness of high-level events, or else is not present    
  7492. sessClosedErr    –917    The kAEDontReconnect flag in the sendMode parameter was set, and the server quit and then restarted    
  7493. errAECoercionFail    –1700    Data could not be coerced to the requested descriptor type    
  7494. errAEDescNotFound    –1701    Descriptor record was not found    
  7495. errAECorruptData    –1702    Data in an Apple event could not be read    
  7496. errAEWrongDataType    –1703    Wrong descriptor type    
  7497. errAENotAEDesc    –1704    Not a valid descriptor record    
  7498. errAEBadListItem    –1705    Operation involving a list item failed    
  7499. errAENewerVersion    –1706    Need a newer version of the Apple Event Manager    
  7500. errAENotAppleEvent    –1707    Event is not an Apple event    
  7501. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event handler    
  7502. errAEReplyNotValid    –1709    AEResetTimer was passed an invalid reply    
  7503. errAEUnknownSendMode    –1710    Invalid sending mode was passed    
  7504. errAEWaitCanceled    –1711    User canceled out of wait loop for reply or receipt    
  7505. errAETimeout    –1712    Apple event timed out    
  7506. errAENoUserInteraction    –1713    No user interaction allowed    
  7507. errAENotASpecialFunction    –1714    The keyword is not valid for a special function    
  7508. errAEParamMissed    –1715    Handler cannot understand a parameter the client considers required    
  7509. errAEUnknownAddressType    –1716    Unknown Apple event address type    
  7510. errAEHandlerNotFound    –1717    No handler found for an Apple event or a coercion, or no object callback function found    
  7511. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  7512. errAEIllegalIndex    –1719    Not a valid list index    
  7513. errAEImpossibleRange    –1720    The range is not valid because it is impossible for a range to include the first and last objects that were specified; an example is a range in which the offset of the first object is greater than the offset of the last object    
  7514. errAEWrongNumberArgs    –1721    The number of operands provided for the kAENot logical operator is not 1    
  7515. errAEAccessorNotFound    –1723    There is no object accessor function for the specified object class and token descriptor type    
  7516. errAENoSuchLogical    –1725    The logical operator in a logical descriptor record is not kAEAnd, kAEOr, or kAENot    
  7517. errAEBadTestKey    –1726    The descriptor record in a test key is neither a comparison descriptor record nor a logical descriptor record    
  7518. errAENotAnObjectSpec    –1727    The objSpecifier parameter of AEResolve is not an object specifier record    
  7519. errAENoSuchObject    –1728     A run-time resolution error, for example: object specifier record asked for the third element, but there are only two    
  7520. errAENegativeCount    –1729     Object-counting function returned negative value    
  7521. errAEEmptyListContainer    –1730    The container for an Apple event object is specified by an empty list    
  7522. errAEUnknownObjectType    –1731    Descriptor type of token returned by AEResolve is not known to server application     
  7523. errAERecordingIsAlreadyOn    –1732    Attempt to turn recording on when it is already on    
  7524.  
  7525.  
  7526.  
  7527. Listing 5-0
  7528. Table 5-0
  7529. Creating and Sending Apple Events
  7530. Contents
  7531. Creating an Apple Event5-3
  7532. Adding Parameters to an Apple Event5-5
  7533. Specifying Optional Parameters for an Apple Event5-7
  7534. Specifying a Target Address5-10
  7535. Creating an Address Descriptor Record5-11
  7536. Addressing an Apple Event for Direct Dispatching5-13
  7537. Sending an Apple Event5-13
  7538. Dealing With Timeouts5-20
  7539. Writing an Idle Function5-21
  7540. Writing a Reply Filter Function5-24
  7541. Reference to Creating and Sending Apple Events5-24
  7542. Routines for Creating and Sending Apple Events5-25
  7543. Creating Apple Events5-25
  7544. Creating and Duplicating Descriptor Records5-26
  7545. Creating Descriptor Lists and AE Records5-28
  7546. Adding Items to Descriptor Lists5-29
  7547. Adding Data and Descriptor Records to AE Records5-32
  7548. Adding Parameters and Attributes to Apple Events5-33
  7549. Sending Apple Events5-37
  7550. Application-Defined Routines5-41
  7551. Summary of Creating and Sending Apple Events5-44
  7552. Pascal Summary5-44
  7553. Constants5-44
  7554. Data Types5-48
  7555. Routines for Creating and Sending Apple Events5-50
  7556. Application-Defined Routines5-51
  7557. C Summary5-51
  7558. Constants5-51
  7559. Data Types5-56
  7560. Routines for Creating and Sending Apple Events5-57
  7561. Application-Defined Routines5-59
  7562. Assembly-Language Summary5-59
  7563. Trap Macros5-59
  7564. Result Codes5-60
  7565. Creating and Sending Apple Events
  7566. This chapter describes how your application can use the Apple Event Manager to create and send Apple events. If you want to factor your application for recording, or if you want your application to send Apple events directly to other applications, you can use Apple Event Manager routines to create and send Apple events. 
  7567. Before you read this chapter, you should be familiar with the chapters “Introduction to Interapplication Communication,” “Introduction to Apple Events,” and “Responding to Apple Events” in this book. If you are factoring your application, you should also be familiar with the chapter “Recording Apple Events” in this book.
  7568. This chapter provides the basic information you need to create and send Apple events from your application. To send core and functional-area Apple events, your application must also be able to create object specifier records. For information about object specifier records, see the chapter “Resolving and Creating Object Specifier Records” in this book.
  7569. To allow your application to send Apple events to applications on other computers, you may wish to use the PPCBrowser function, which is described in the chapter “Program-to-Program Communications Toolbox” in this book.
  7570. The first section in this chapter, “Creating an Apple Event,” describes how to
  7571. n    create an Apple event
  7572. n    add parameters to an Apple event
  7573. n    specify optional Apple event parameters
  7574. n    specify a target address
  7575. The section “Sending an Apple Event” describes how to 
  7576. n    send an Apple event
  7577. n    deal with timeouts
  7578. n    write an idle function
  7579. n    write a reply filter function
  7580.  
  7581. Creating an Apple Event
  7582.  
  7583. You create an Apple event by using the AECreateAppleEvent function. You supply parameters that specify the event class and event ID, the target address, the return ID, and the transaction ID, and a buffer for the returned Apple event. The AECreateAppleEvent function creates and returns, in the buffer you specify, an Apple event with the attributes set as your application requested. You should not directly manipulate the contents of the Apple event; rather, use Apple Event Manager functions to add additional attributes or parameters to it.
  7584. The example that follows creates an imaginary Multiply event using the AECreateAppleEvent function.
  7585. myErr := AECreateAppleEvent(kArithmeticClass, kMultEventID,
  7586.                                      targetAddress, kAutoGenerateReturnID,
  7587.                                      kAnyTransactionID, theAppleEvent);  
  7588. The event class, specified by the kArithmeticClass constant, identifies this event as belonging to a class of Apple events for arithmetic operations. The event ID specifies the particular Apple event within the class—in this case, an Apple event that performs multiplication.
  7589. You specify the target of the Apple event in the third parameter to AECreateAppleEvent. The target address can identify an application on the local computer or another computer on the network. You can specify the address using a target ID record or session reference number. For processes on the local computer, you can also use a process serial number or application signature to specify the address. See “Specifying a Target Address” on page 5-10 for more information. 
  7590. In the fourth parameter, you specify the return ID of the Apple event, which associates this Apple event with the server’s reply. The AECreateAppleEvent function assigns the specified return ID value to the keyReturnIDAttr attribute of the Apple event. If a server returns a standard reply Apple event (that is, an event of event class 'aevt' and event ID 'ansr') in response to this event, the Apple Event Manager assigns the reply event the same return ID. When you receive a reply Apple event, you can check the keyReturnIDAttr attribute to determine which outstanding Apple event the reply is responding to. You can use the kAutoGenerateReturnID constant to request that the Apple Event Manager generate a return ID that is unique to this session for the Apple event. Otherwise, you are responsible for making it unique. 
  7591. The fifth parameter specifies the transaction ID attribute of the Apple event. A transaction is a sequence of Apple events that are sent back and forth between the client and server applications, beginning with the client’s initial request for a service. All Apple events that are part of one transaction must have the same transaction ID.
  7592. You can use a transaction ID to indicate that an Apple event is one of a sequence of Apple events related to a single transaction. The kAnyTransactionID constant indicates that the Apple event is not part of a transaction.
  7593. The AECreateAppleEvent function creates an Apple event with only the specified attributes and no parameters. To add parameters or additional attributes, you can use other Apple Event Manager functions.
  7594. Adding Parameters to an Apple Event
  7595.  
  7596. You can use the AEPutParamPtr or AEPutParamDesc function to add parameters to an Apple event. When you use either of these functions, the Apple Event Manager adds the specified parameter to the Apple event. 
  7597. Use the AEPutParamPtr function when you want to add data specified in a buffer as the parameter of an Apple event. You specify the Apple event, the keyword of the parameter to add, the descriptor type, a buffer that contains the data, and the size of this buffer as parameters to the AEPutParamPtr function. The AEPutParamPtr function adds the data to the Apple event as a parameter with the specified keyword.
  7598. For example, this code adds a parameter to the Multiply event using the AEPutParamPtr function:
  7599. CONST        keyOperand1 = 'OPN1';
  7600. VAR
  7601.     number1:                        LongInt;
  7602.     theAppleEvent:                        AppleEvent;
  7603.     myErr:                        OSErr;
  7604.  
  7605. number1 := 10;
  7606. myErr := AEPutParamPtr(theAppleEvent, keyOperand1, 
  7607.                               typeLongInteger, @number1,
  7608.                               SizeOf(number1));
  7609. In this example, the Apple Event Manager adds the parameter containing the first number to the specified Apple event. 
  7610. Use the AEPutParamDesc function to add a descriptor record to an Apple event. The descriptor record you specify must already exist. To create or get a descriptor record, you can use the AECreateDesc, AEDuplicateDesc, and other Apple Event Manager functions that return a descriptor record.
  7611. When you create a descriptor record using the AECreateDesc function, you specify the descriptor type, a buffer that contains the data, and the size of this buffer as parameters. The AECreateDesc function returns the descriptor record that describes the data.
  7612. This example creates a descriptor record for the second parameter of the Multiply event:
  7613. VAR
  7614.     number2:                         LongInt;
  7615.     multParam2Desc:                        AEDesc;
  7616.     myErr:                        OSErr;
  7617.  
  7618. number2 := 8;
  7619. myErr := AECreateDesc(typeLongInteger, @number2, SizeOf(number2),
  7620.                              multParam2Desc); 
  7621. In this example, the AECreateDesc function creates a descriptor record with the typeLongInteger descriptor type and the data identified in the number2 variable.
  7622. Once you have created a descriptor record, you can use AEPutParamDesc to add the data to an Apple event parameter. You specify the Apple event to add the parameter to, the keyword of the parameter, and the descriptor record of the parameter as parameters to the AEPutParamDesc function.
  7623. This example adds a second parameter to the Multiply event using the AEPutParamDesc function:
  7624. CONST        keyOperand2 = 'OPN2';
  7625.  
  7626. myErr := AEPutParamDesc(theAppleEvent, keyOperand2, 
  7627.                                 multParam2Desc);
  7628. This example adds the keyOperand2 keyword and the descriptor record created in the previous example as the second parameter to the specified Apple event. 
  7629. You can also create a descriptor record without using Apple Event Manager routines. For example, this example generates an alias descriptor record from an existing alias handle:
  7630. WITH myAliasDesc DO
  7631.     BEGIN
  7632.         descriptorType := typeAlias;
  7633.         dataHandle := myAliasHandle;
  7634.     END;
  7635. Whatever method you use to create a descriptor record, you can add it to an Apple event parameter by using AEPutParamDesc.
  7636. After adding parameters to an Apple event, you can send the Apple event using the AESend function. See “Sending an Apple Event,” which begins on page 5-13, for information about using this function.
  7637. Specifying Optional Parameters for an Apple Event
  7638.  
  7639. The parameters for a given Apple event are listed in the Apple Event Registry: Standard Suites as either required or optional. Your application does not usually have to include Apple event parameters that are listed as optional; the target application uses default values for parameters that are listed as optional if your application does not provide them. The Apple Event Registry: Standard Suites defines the default value a target application should use for each optional parameter of a specific Apple event. 
  7640. The guidelines listed in the Apple Event Registry: Standard Suites for which parameters should be considered optional and which should be considered required are not enforced by the Apple Event Manager. Instead, the source application indicates which Apple event parameters it considers optional by listing the keywords for those parameters in the keyOptionalKeywordAttr attribute. 
  7641. The keyOptionalKeywordAttr attribute does not contain the optional parameters; it simply lists the keywords of any parameters for the Apple event that the source application wants to identify as optional. Although the source application is responsible for providing this information in the keyOptionalKeywordAttr attribute of an Apple event, it is not required to provide this attribute.
  7642. If a keyword for an Apple event parameter is not included in the keyOptionalKeywordAttr attribute, the source application expects the target application to understand the Apple event parameter identified by that keyword. If a target application cannot understand the parameter, it should return the result code errAEParamMissed and should not attempt to handle the event.
  7643. If a keyword for an Apple event parameter is included in the keyOptionalKeywordAttr attribute, the source application does not require the target application to understand the Apple event parameter identified by that keyword. If the target application cannot understand a parameter whose keyword is included in the keyOptionalKeywordAttr attribute, it should ignore that parameter and attempt to handle the Apple event as it normally does.
  7644. A source application can choose not to list the keyword for an Apple event parameter in the keyOptionalKeywordAttr attribute even if that parameter is listed in the Apple Event Registry: Standard Suites as an optional parameter. This has the effect of forcing the target application to treat the parameter as required for a particular Apple event. If the target application supports the parameter, it should handle the Apple event as the client application expects. If the target application does not support the parameter and calls an application-defined routine such as MyGotRequiredParams to check whether it has received all the required parameters, it finds that there’s another parameter that the client application considered required, and should return the result code errAEParamMissed. 
  7645. If a source application wants a target application to attempt to handle an Apple event regardless of whether the target application supports a particular Apple event parameter included in that Apple event, the source application should list the keyword for that parameter in the keyOptionalKeywordAttr attribute. 
  7646. It is up to the source application to decide whether to list a parameter that is described as optional in the Apple Event Registry: Standard Suites in the keyOptionalKeywordAttr attribute of an Apple event. For example, suppose a source application has extended the definition of the Print event to include an optional keyColorOrGrayscale parameter that specifies printing in color or gray scale rather than black and white. The source application might decide whether or not to list the keyword keyColorOrGrayscale in the keyOptionalKeywordAttr attribute according to the characteristics of the print request. If the source application requires the target application to print a document in color, the source application could choose not to add the keyword keyColorOrGrayscale to the keyOptionalKeywordAttr attribute; in this case, only target applications that supported the keyColorOrGrayscale parameter would attempt to handle the event. If the source application does not require the document printed in color, it could choose to add the keyword keyColorOrGrayscale to the keyOptionalKeywordAttr attribute; in this case, the target application will attempt to handle the event regardless of whether it supports the keyColorOrGrayscale parameter.
  7647. Your application can add optional parameters to an Apple event the same way it adds required parameters, using the AECreateDesc, AEPutParamPtr, and AEPutParamDesc functions as described in the previous section, “Adding Parameters to an Apple Event.” If your application chooses to provide the keyOptionalKeywordAttr attribute for an Apple event, it should first create a descriptor list that specifies the keywords of the optional parameters, then add it to the Apple event as a keyOptionalKeywordAttr attribute. 
  7648. Listing 5-1 shows an application-defined routine, MyCreateOptionalKeyword, that creates the keyOptionalKeywordAttr attribute for the Create Publisher event.
  7649. Listing 5-1    Creating the optional keyword for the Create Publisher event
  7650.  
  7651. FUNCTION MyCreateOptionalKeyword
  7652.                                 (VAR createPubAppleEvent: AppleEvent)
  7653.                                  : OSErr;
  7654. VAR
  7655.     optionalList:                    AEDescList;
  7656.     myOptKeyword1:                    AEKeyword;
  7657.     myOptKeyword2:                    AEKeyword;
  7658.     myErr:                    OSErr;
  7659.     ignoreErr:                    OSErr;
  7660. BEGIN                                
  7661.     myOptKeyword1 := keyDirectObject;
  7662.     {create an empty descriptor list}
  7663.     myErr := AECreateList(NIL, 0, FALSE, optionalList);
  7664.     IF myErr = noErr THEN 
  7665.     BEGIN
  7666.         {add the keyword of the first optional parameter}
  7667.         myErr := AEPutPtr(optionalList, 1, typeKeyword, 
  7668.                                 @myOptKeyword1, SizeOf(myOptKeyword1));
  7669.         IF myErr = noErr THEN 
  7670.         BEGIN
  7671.             {add the keyword of the next optional parameter}
  7672.             myOptKeyword2 := keyAEEditionFileLoc;
  7673.             myErr := AEPutPtr(optionalList, 2, typeKeyword, 
  7674.                                     @myOptKeyword2, SizeOf(myOptKeyword2));
  7675.         END;
  7676.         IF myErr = noErr THEN 
  7677.             {create the keyOptionalKeywordAttr attribute and add it }
  7678.             { to the Create Publisher event}
  7679.             myErr :=     AEPutAttributeDesc(createPubAppleEvent,
  7680.                                                  keyOptionalKeywordAttr, 
  7681.                                                  optionalList);
  7682.     END;
  7683.     ignoreErr := AEDisposeDesc(optionalList);
  7684.     MyCreateOptionalKeyword := myErr;
  7685. END;
  7686. The MyCreateOptionalKeyword function shown in Listing 5-1 adds to a descriptor list the keyword of each parameter that the source application considers optional. Each keyword is added as a descriptor record with the descriptor type typeKeyword. The function specifies that the target application can handle the Create Publisher event without supporting parameters identified by the keywords keyDirectObject and keyAEEditionFileLoc. (These are the parameters that specify the Apple event object to publish and the location of the edition container; if these parameters are missing, the target application creates a publisher for the current selection using the application’s default edition container.) After adding these keywords to the descriptor list, the function creates the keyOptionalKeywordAttr attribute using the AEPutAttributeDesc function.
  7687. Typically a target application does not examine the keyOptionalKeywordAttr attribute directly. Instead, a target application that supports a parameter listed as optional in the Apple Event Registry: Standard Suites attempts to extract it from the Apple event (using AEGetParamDesc, for example). If it can’t extract the parameter, the target application uses the default value, if any, listed in the Apple Event Registry. A target application can use the keyMissedKeywordAttr attribute to return the first required parameter (that is, considered required by the source application), if any, that it did not retrieve from the Apple event. The keyMissedKeywordAttr attribute does not return any parameters whose keywords are listed in the keyOptionalKeywordAttr attribute of the Apple event.        
  7688. Specifying a Target Address
  7689.  
  7690. When you create an Apple event, you must specify the address of the target. The target address identifies the particular application or process to which you want to send the Apple event. You can send Apple events to applications on the local computer or on remote computers on the network. 
  7691. These are the descriptor types that identify the four methods of addressing an Apple event:typeApplSignature    The application signature of the target    
  7692. typeSessionID    The session reference number of the target    
  7693. typeTargetID    The target ID record of the target    
  7694. typeProcessSerialNumber    The process serial number of the target    
  7695.  
  7696. To address an Apple event to a target on a remote computer on the network, you must use either the typeSessionID or typeTargetID descriptor type.   
  7697. If your application sends an Apple event to itself, it should address the Apple event using a process serial number of kCurrentProcess. This is the fastest way for your application to send an Apple event to itself. For more information, see “Addressing an Apple Event for Direct Dispatching” on page 5-13.
  7698. You can use any of the four address types when sending an Apple event to another application on the local computer. The chapter “Event Manager” in Inside Macintosh: Macintosh Toolbox Essentials describes all four types of addresses. Your application can also use another address type if it provides a coercion handler that coerces the address type into one of the four address types that the Apple Event Manager recognizes. See “Writing and Installing Coercion Handlers,” which begins on page 4-41, for more information.
  7699. To allow the user to choose the target of an Apple event, use the PPCBrowser function. This function presents a standard user interface for choosing a target application, much as the Standard File Package provides a standard user interface for opening and saving files. The PPCBrowser function returns, in a target ID record, information about the application the user chose. Listing 5-3 on page 5-12 shows how to use the PPCBrowser function to let the user choose a target. 
  7700. Creating an Address Descriptor Record
  7701.  
  7702. You specify the address using an address descriptor record (a descriptor record of data type AEAddressDesc). You must create a descriptor record of this type and then add it to the Apple event using the AECreateAppleEvent function.
  7703. You can use the AECreateDesc function to create address descriptor records for any of the four types of target addresses. Listing 5-2 shows four possible ways to create an address, each using a different address type.
  7704. Listing 5-2    Creating a target address
  7705.  
  7706. PROCEDURE MySetTargetAddresses(VAR targetAddress1, 
  7707.                                            targetAddress2, targetAddress3, 
  7708.                                          targetAddress4: AEAddressDesc; 
  7709.                                          toTargetID: TargetID; 
  7710.                                           thePSN: ProcessSerialNumber; 
  7711.                                          theSignature: OSType; 
  7712.                                          theSessionRef: PPCSessRefNum);
  7713. VAR
  7714.     myErr:             OSErr;
  7715. BEGIN
  7716.     myErr := AECreateDesc(typeTargetID, @toTargetID,
  7717.                                  SizeOf(toTargetID), targetAddress1);
  7718.     myErr := AECreateDesc(typeProcessSerialNumber, @thePSN, 
  7719.                                  SizeOf(thePSN), targetAddress2);
  7720.     myErr := AECreateDesc(typeApplSignature, @theSignature, 
  7721.                                  SizeOf(theSignature), targetAddress3);
  7722.     myErr := AECreateDesc(typeSessionID, @theSessionRef, 
  7723.                                  SizeOf(theSessionRef), targetAddress4);
  7724.     {add your own error checking}
  7725. END;
  7726. To create an address descriptor record, specify the following as parameters to AECreateDesc: the descriptor type for the address, a pointer to the buffer containing the address, and the size of the buffer. The AECreateDesc function returns an address descriptor record with the specified characteristics.
  7727. After creating an address, you can specify it as a parameter to the AECreateAppleEvent function. See “Creating an Apple Event,” which begins on page 5-3, for an example using the AECreateAppleEvent function. 
  7728. When you specify an address to the AECreateAppleEvent function, the Apple Event Manager stores the address in the keyAddressAttr attribute of the Apple event. 
  7729. If you use the PPCBrowser function to allow the user to choose an Apple event’s target, your application must create a target ID record based on the user’s choice. Listing 5-3 shows how to create a target ID record using the information returned from the PPCBrowser function and create an address descriptor record using the AECreateDesc function.
  7730. Listing 5-3    Specifying a target address in an Apple event by using the PPCBrowser function
  7731.  
  7732. FUNCTION MyGetTargetAddress (myPrompt: Str255; myAppStr: Str255;
  7733.                                         VAR myPortInfo: PortInfoRec; 
  7734.                                         VAR targetAddress: AEAddressDesc; 
  7735.                                         VAR toTargetID: targetID): OSErr;
  7736. VAR
  7737.     myErr:            OSErr;
  7738. BEGIN                        
  7739.     {use PPCBrowser to let user choose the target}
  7740.     myErr := PPCBrowser(myPrompt, myAppStr, FALSE, 
  7741.                                 toTargetID.location, 
  7742.                                 myPortInfo, NIL, '');
  7743.     MyGetTargetAddress := myErr;
  7744.     IF myErr <> noErr THEN Exit(MyGetTargetAddress);
  7745.  
  7746.     toTargetID.name := myPortInfo.name;
  7747.  
  7748.     {create the descriptor record for the target address}
  7749.     MyGetTargetAddress := AECreateDesc(typeTargetID, @toTargetID, 
  7750.                                                      SizeOf(toTargetID), 
  7751.                                                     targetAddress);
  7752. END;
  7753. See the chapter “Program-to-Program Communications Toolbox” in this book for more information on using the PPCBrowser function.
  7754. Addressing an Apple Event for Direct Dispatching
  7755.  
  7756. As described in the chapter “Recording Apple Events” in this book, a recordable application must send itself Apple events in response to user actions. Your application can send itself Apple events by using an address descriptor record of descriptor type typeProcessSerialNumber with the lowLongOfPSN field set to kCurrentProcess and the highLongOfPSN set to 0. The Apple Event Manager processes such Apple events immediately, executing the appropriate Apple event handler directly without going through the normal event-processing sequence. For this reason, your application will not appear to run more slowly when it sends Apple events to itself.  
  7757. Apple events your application sends to itself this way do not appear in your application’s high-level event queue. This not only speeds up delivery of the event but also avoids situations in which an Apple event sent in response to a user action arrives in the event queue after some other event that really occurred later than the user action. For example, suppose a user chooses Cut from the Edit menu and then clicks in another window. If the Cut event arrives in the queue after the window activate event, a selection in the wrong window might be cut.
  7758. Your application can send events to itself using other forms of addressing, such as the true process serial number returned by GetCurrentProcess. Because direct dispatching avoids event sequence problems, applications should generally send events to themselves by using an address descriptor record of descriptor type typeProcessSerialNumber with the kCurrentProcess constant rather than using a true process serial number or an application signature. 
  7759. IMPORTANT
  7760. When Apple event recording has been turned on, the Apple Event Manager records every event that your application sends to itself unless you specify the kAEDontRecord flag in the sendMode parameter of the AESend function.s 
  7761.  
  7762. Sending an Apple Event
  7763.  
  7764. To send an Apple event, you first create an Apple event, add parameters and attributes to it, and then use the AESend function to send it. 
  7765. When you send an Apple event, you specify various options to indicate how the server should handle the Apple event. You request a user interaction level from the server and specify whether the server can switch directly to the foreground if user interaction is needed, whether your application is willing to wait for a reply Apple event, whether reconnection is allowed, and whether your application wants a return receipt for the Apple event. 
  7766. You specify these options by setting flags in the sendMode parameter for AESend. Here are the constants that represent these flags:
  7767. CONST         kAENoReply                        = $00000001;                {client doesn't want reply}
  7768.         kAEQueueReply                        = $00000002;    {client wants Apple Event } 
  7769.                                                 { Manager to return }
  7770.                                                 { reply in event queue}
  7771.         kAEWaitReply                        = $00000003;        {client wants a reply and }
  7772.                                                 { will give up processor}
  7773.  
  7774.         kAENeverInteract                        = $00000010;        {server application }
  7775.                                                 { should not interact }
  7776.                                                 { with user for this }
  7777.                                                 { Apple event}
  7778.         kAECanInteract                        = $00000020;    {server may interact with }
  7779.                                                 { user for this Apple }
  7780.                                                 { event to supply } 
  7781.                                                 { information}
  7782.         kAEAlwaysInteract                        = $00000030;    {server may interact with }
  7783.                                                 { user for this Apple }
  7784.                                                 { event even if no }
  7785.                                                 { information                 is required}
  7786.  
  7787.         kAECanSwitchLayer                        = $00000040;    {server should come }
  7788.                                                 { directly to foreground }
  7789.                                                 { when appropriate}
  7790.         kAEDontReconnect                        = $00000080;    {don't reconnect if there }
  7791.                                                 { is a PPC session closed }
  7792.                                                 { error}
  7793.         kAEWantReceipt                        = nReturnReceipt;                {client wants return }
  7794.                                                       { receipt}
  7795.         kAEDontRecord                        = $00001000;                {don’t record this event}
  7796.         kAEDontExecute                        = $00002000;    {don’t execute this event}
  7797. If you want your application to receive a reply Apple event, specify the kAEQueueReply or kAEWaitReply flag. If you want your application to receive the reply Apple event in its event queue, use kAEQueueReply. If you want your application to receive the reply Apple event in the reply parameter for AESend and you are willing to give up the processor while it is waiting for the reply, use kAEWaitReply. If you don’t want your application to receive a reply Apple event and your application doesn’t need to wait for the server to handle the Apple event, specify kAENoReply. 
  7798. Note
  7799. Note
  7800. Before the Apple Event Manager sends a reply event back to the client application, the keyAddressAttr attribute contains the address of the client application. After the client receives the reply event, the keyAddressAttr attribute contains the address of the server application.u
  7801. If you specify kAENoReply or kAEQueueReply, the AESend function returns immediately after using the Event Manager to send the event. In this case, a noErr result code from AESend indicates that the Event Manager sent the Apple event; it does not mean that the server accepted or handled the Apple event. 
  7802. When AESend returns, the reply parameter does not contain valid data if your application specifies kAENoReply or kAEQueueReply. The kAENoReply flag indicates that the Apple Event Manager will not return the reply Apple event to your application. The kAEQueueReply flag indicates that you want your application to receive the reply via its event queue rather than the reply parameter of AESend. If you specify kAEQueueReply, you must install a handler for the reply Apple event (event class kCoreEventClass and event ID kAEAnswer). 
  7803. If you specify kAEWaitReply, the Apple Event Manager uses the Event Manager to send the event. The Apple Event Manager then calls the WaitNextEvent function on behalf of your application, causing your application to yield the processor and giving the server application a chance to receive and handle the Apple event. Your application continues to yield the processor until the server handles the Apple event or the request times out. 
  7804. If you specify kAEWaitReply, you must provide an idle function. This function should process any update events, null events, operating-system events, or activate events that occur while your application is waiting for a reply. See “Writing an Idle Function,” which begins on page 5-21, for sample code that shows an idle function. 
  7805. You use one of the three flags—kAENeverInteract, kAECanInteract, and kAEAlwaysInteract—to specify whether the server should interact with the user when handling the Apple event. Specify kAENeverInteract if the server should not interact with the user when handling the Apple event. You might specify this constant if you don’t want the user to be interrupted while the server is handling the Apple event.
  7806. Use the kAECanInteract flag if the server should interact with the user when the user needs to supply information to the server. Use the kAEAlwaysInteract flag if the server should interact with the user whenever the server normally asks a user to confirm a decision or interact in any other way, even if no additional information is needed from the user. Note that it is the responsibility of the server and client applications to agree on how to interpret the kAEAlwaysInteract flag. 
  7807. If the client application does not set any one of the user interaction flags, the Apple Event Manager sets a default, depending on the location of the target of the Apple event. If the server application is on a remote computer, the Apple Event Manager sets the kAENeverInteract flag as the default. If the target of the Apple event is on the local computer, the Apple Event Manager sets the kAECanInteract flag as the default.
  7808. The server application should call AEInteractWithUser if it needs to interact with the user. If both the client and the server allow user interaction, the Apple Event Manager attempts to bring the server to the foreground if it is not already the foreground process. If both the kAECanSwitchLayer and the kAEWaitReply flags are set, and if the client application is the active application on the local computer, the Apple Event Manager brings the server application directly to the front. Otherwise, the Apple Event Manager posts a notification request asking the user to bring the server application to the front, regardless of whether the kAECanSwitchLayer flag is set. This ensures that the user will not be interrupted by an unexpected application switch. 
  7809. You should specify the kAECanSwitchLayer flag only when the client and server applications reside on the same computer. In general, you should not set this flag if it would be confusing or inconvenient to the user for the server application to come to the front unexpectedly. This flag is ignored if you are sending an Apple event to a remote computer.
  7810. Specify the kAEDontReconnect flag if the Apple Event Manager should not reconnect if it receives a session closed error from the PPC Toolbox. If you don’t set this flag, the Apple Event Manager automatically attempts to reconnect and reestablish the session.
  7811. Specify the kAEWantReceipt flag if your application wants notification that the server application has accepted the Apple event. If you specify this flag, your application receives a return receipt as a high-level event.
  7812. If you specify the kAEWantReceipt flag and the server application does not accept the Apple event within the time specified by the timeOutInTicks parameter to AESend, the AESend function returns a timeout error. Note that AESend also returns a timeout error if your application sets the kAEWaitReply flag and does not receive the reply Apple event within the time specified by the timeOutInTicks parameter.
  7813. Specify the kAEDontRecord flag if your application is sending an Apple event to itself that you don’t want to be recorded. When Apple event recording has been turned on, every event that your application sends to itself will be automatically recorded by the Apple Event Manager except those sent with the kAEDontRecord flag set.
  7814. Specify the kAEDontExecute flag if your application is sending an Apple event to itself for recording purposes only—that is, if you want the Apple Event Manager to send a copy of the event to the recording process but you do not want your application actually to receive the event. (For more information about when to use the kAEDontExecute flag, see the chapter “Recording Apple Events” in this book.)
  7815. Listing 5-4 illustrates how to send a Multiply event (an imaginary Apple event for multiplying two long integers). It first creates an Apple event, adds parameters containing the numbers to multiply, then sends it, specifying various options. It also illustrates how to handle the reply Apple event that contains the result.
  7816. Note
  7817. Note
  7818. If you want to send Apple events, your application must set flags in its 'SIZE' resource indicating that it can handle high-level events, and it must provide handlers for the required Apple events. See “Accepting an Apple Event” on page 4-5 for information on setting the appropriate flags in the 'SIZE' resource and “Handling the Required Apple Events” on page 4-11 for information on supporting the required Apple events.u
  7819. Listing 5-4    Sending an Apple event
  7820.  
  7821. FUNCTION MySendMultiplyEvent (serverAddress: AEAddressDesc;
  7822.                                         firstOperand: LongInt; secondOperand:                     LongInt;
  7823.                                         VAR replyResultLongInt: LongInt): OSErr;
  7824. CONST
  7825.     kArithmeticClass                         =    'ARTH';             {event class for arithmetic }
  7826.                                             { Apple events}
  7827.     kMultiplyEventID                         =    'MULT';             {event ID for Multiply event}
  7828.     keyMultOperand1                        =     'OPN1';            {keyword for first parameter}
  7829.     keyMultOperand2                        =     'OPN2';             {keyword for second parameter}
  7830. VAR
  7831.     theAppleEvent:                         AppleEvent;
  7832.     reply:                         AppleEvent;
  7833.     returnedType:                        DescType;
  7834.     actualSize:                         LongInt;
  7835.     myErr:                        OSErr;
  7836.     ignoreErr:                        OSErr; 
  7837.     errStr:                        Str255;
  7838.     errNumber:                        LongInt;
  7839. BEGIN
  7840.     myErr := AECreateAppleEvent(kArithmeticClass, kMultiplyEventID, 
  7841.                                          serverAddress, kAutoGenerateReturnID,
  7842.                                          kAnyTransactionID, theAppleEvent);
  7843.     IF myErr = noErr THEN 
  7844.         {add the first operand}
  7845.         myErr := AEPutParamPtr(theAppleEvent, keyMultOperand1, 
  7846.                                       typeLongInteger, @firstOperand, 
  7847.                                         SizeOf(firstOperand));
  7848.     {add the second operand with the proper keyword}
  7849.     IF myErr = noErr THEN
  7850.         myErr := AEPutParamPtr(theAppleEvent, keyMultOperand2, 
  7851.                                       typeLongInteger, @secondOperand, 
  7852.                                       SizeOf(secondOperand));
  7853.  
  7854.     IF myErr = noErr THEN
  7855.         myErr := AESend(theAppleEvent, reply, kAEWaitReply +             kAENeverInteract,
  7856.                           kAENormalPriority, 120, @MyIdleFunction, NIL);
  7857.     IF myErr = noErr THEN {Apple event successfully sent}
  7858.     BEGIN              {Check whether it was successfully handled-- }
  7859.                { get result code returned by the server's handler}
  7860.         myErr := AEGetParamPtr(reply, keyErrorNumber, typeLongInteger, 
  7861.                                       returnedType, @errNumber, SizeOf(errNumber), 
  7862.                                       actualSize);
  7863.  
  7864.         IF (myErr = errAEDescNotFound) OR (errNumber = noErr) THEN
  7865.         {if keyErrorNumber doesn't exist or server returned noErr }
  7866.         { then the Apple event was successfully handled--the reply Apple }
  7867.         { event contains the result in the direct parameter}
  7868.             myErr := AEGetParamPtr(reply, keyDirectObject, typeLongInteger, 
  7869.                                           returnedType, @replyResultLongInt,
  7870.                                           SizeOf(replyResultLongInt), actualSize)
  7871.         ELSE
  7872.         BEGIN            {server returned an error, so get error string}
  7873.             myErr := AEGetParamPtr(reply, keyErrorString, typeChar, 
  7874.                                             returnedType, @errStr[1], SizeOf(errStr)-1, 
  7875.                                           actualSize);
  7876.             IF myErr = noErr THEN
  7877.             BEGIN
  7878.                 IF actualSize > 255 THEN
  7879.                     actualSize := 255;
  7880.                 errStr[0] := chr(actualSize);
  7881.                 MyDisplayError(errStr);
  7882.             END;
  7883.         END;
  7884.     ignoreErr := AEDisposeDesc(reply);
  7885.     END
  7886.     ELSE
  7887.     BEGIN
  7888.         {the Apple event wasn't successfully dispatched, }
  7889.         { the request timed out, the user canceled, or other error} 
  7890.     END;
  7891.     ignoreErr := AEDisposeDesc(theAppleEvent);
  7892.     MySendMultiplyEvent := myErr;
  7893. END;
  7894. The code in Listing 5-4 first creates an Apple event with kArithmeticClass as the event class and kMultiplyEventID as the event ID. It also specifies the server of the Apple event. See “Specifying a Target Address” on page 5-10 for information on specifying a target address and “Creating an Apple Event,” which begins on page 5-3, for more information on creating an Apple event.
  7895. The Multiply event shown in Listing 5-4 contains two parameters, each specifying a number to multiply. See “Adding Parameters to an Apple Event” on page 5-5 for examples of how to specify the parameters for the AEPutParamPtr function. 
  7896. After adding the parameters to the event, the code uses AESend to send the event. The first parameter to AESend specifies the Apple event to send—in this example, the Multiply event. The next parameter specifies the reply Apple event. 
  7897. This example specifies kAEWaitReply in the third parameter, indicating that the client is willing to yield the processor for the specified timeout value (120 ticks, or 2 seconds). The kAENeverInteract flag indicates that the server should not interact with the user when processing the Apple event. The fourth parameter specifies that the Multiply event is to be sent using normal priority (that is, placed at the end of the event queue). You can specify the kAEHighPriority flag to place the event in the front of the event queue, but this is not usually recommended.
  7898. The next to last parameter specifies the address of an idle function. If you specify kAEWaitReply, you must provide an idle function. This function should process any update events, null events, operating-system events, or activate events that occur while your application is waiting for a reply. See “Writing an Idle Function,” which begins on page 5-21, for sample code that shows an idle function. 
  7899. The last parameter to AESend specifies a filter function. You can supply a filter function to filter high-level events that your application may receive while waiting for a reply Apple event. You can specify NIL for this parameter if you do not need to filter high-level events while waiting for a reply. See “Writing a Reply Filter Function” on page 5-24 for more information. 
  7900. If you specify kAEWaitReply, a noErr result code from AESend indicates that the Apple event was sent successfully, not that the server has completed the requested action successfully. Therefore, you should find out whether a result code was returned from the handler by checking the reply Apple event for the existence of either the keyErrorNumber or keyErrorString parameter. If the keyErrorNumber parameter does not exist or contains the noErr result code, you can use AEGetParamPtr to get the parameter you’re interested in from the reply Apple event. 
  7901. The MySendMultiplyEvent function in Listing 5-4 checks the function result of AESend. If it is noErr, MySendMultiplyEvent checks the keyErrorNumber parameter of the reply Apple event to determine whether the server successfully handled the Apple event. If this parameter exists and indicates that an error occurred, MySendMultiplyEvent gets the error string out of the keyErrorString parameter. Otherwise, the server performed the request, and the reply Apple event contains the answer to the multiplication request.
  7902. When you have finished using the Apple event specified in the AESend function and no longer need the reply Apple event, you must dispose of both the original event and the reply by calling the AEDisposeDesc function.
  7903. IMPORTANT
  7904. If your application sends Apple events to itself using a typeProcessSerialNumber address descriptor record with the lowLongOfPSN field set to kCurrentProcess, the Apple Event Manager jumps directly to the appropriate Apple event handler without going through the normal event-processing sequence. For this reason, your application will not appear to run more slowly when it sends Apple events to itself. For more information, see “Addressing an Apple Event for Direct Dispatching” on page 5-13.s 
  7905. Dealing With Timeouts
  7906.  
  7907. When your application calls AESend and chooses to wait for the server application to handle the Apple event, it can also specify the maximum amount of time it is willing to wait for a response. You can specify a timeout value in the timeOutInTicks parameter to AESend. You can either specify a particular length of time, in ticks, that your application is willing to wait, or you can specify the kNoTimeOut constant or the kAEDefaultTimeout constant. 
  7908. Use the kNoTimeOut constant to indicate that your application is willing to wait forever for a response from the server. You should use this value only if you are sure that the server will respond in a reasonable amount of time. You should also implement a method of checking whether the user wants to cancel. The idle function that you specify as a parameter to AESend should check the event queue for any instances of Command-period and immediately return TRUE as its function result if it finds a request to cancel in the event queue.
  7909. Use the kAEDefaultTimeout constant if you want the Apple Event Manager to use a default timeout value. The Apple Event Manager uses a timeout value of about one minute if you specify this constant.
  7910. If you set the kAEWaitReply flag and the server doesn’t have a handler for the Apple event, the server immediately returns the errAEEventNotHandled result code. If the server doesn’t respond within the length of time specified by the timeout value, AESend returns the errAETimeout result code and a reply Apple event that contains no data. This result code does not necessarily mean that the server failed to perform the requested action; it means only that the server did not complete processing within the specified time. The server might still be processing the Apple event, and it might still send a reply.
  7911. If the server finishes processing the Apple event sometime after the time specified in the keyTimeoutAttr attribute has expired, it returns a reply Apple event to AEProcessAppleEvent. The Apple Event Manager then adds the actual data to the reply. Thus, your application can continue to check the reply Apple event to see if the server has responded, even after the time expires. If the server has not yet sent the reply when the client attempts to extract data from the reply Apple event, the Apple Event Manager functions return the errAEReplyNotArrived result code. After the reply Apple event returns from the server, the client can extract the data in the reply.
  7912. Additionally, the server can examine the keyTimeoutAttr attribute of the Apple event to determine the timeout value specified by the client. You can use the value of this attribute as a rough estimate of how much time your handler has to respond. You can assume that your handler has less time to respond than the timeout value, because transmitting the Apple event uses some of the available time, as does transmitting the reply Apple event back to the client, and the event may have been in the queue for a while already.
  7913. If you set the kAENoReply or kAEQueueReply flag, the Apple Event Manager ignores any timeout value you specify, because your application is not waiting for the reply. An attempt by the server to examine the keyTimeoutAttr attribute in this situation generates the error errAEDescNotFound.
  7914. If your handler needs more time than is specified in the keyTimeoutAttr attribute, you can reset the timer by using the AEResetTimer function. This function resets the timeout value of an Apple event to its starting value.
  7915. Writing an Idle Function
  7916.  
  7917. This section describes how to write an idle function for use with the AESend or AEInteractWithUser function.
  7918. When your application sends an Apple event, you can set one of three flags in the sendMode parameter to AESend that specify how you want to deal with the reply: kAENoReply if you don’t want your application to receive a reply, kAEQueueReply if you want it to receive the reply in its event queue, or kAEWaitReply if you want the reply returned in the reply parameter of AESend and you are willing to give up the processor while your application is waiting for the reply.
  7919. If you specify kAENoReply or kAEQueueReply, the AESend function returns immediately after using the Event Manager to send the event. If you specify kAEWaitReply, the AESend function does not return until either the server application finishes handling the Apple event or a specified amount of time expires. In this case the AESend function calls WaitNextEvent on behalf of your application. This yields the processor to other processes, so that the server has an opportunity to receive and process the Apple event sent by your application. While your application is waiting for a reply, it cannot receive events unless it provides an idle function.
  7920. If you provide a pointer to an idle function as a parameter to the AESend function, AESend calls your idle function whenever an update event, null event, operating-system event, or activate event is received for your application. To allow your application to process high-level events that it receives while waiting for a reply, provide a reply filter function. See the next section, “Writing a Reply Filter Function,” for more information.
  7921. Your application can yield the processor in a similar manner when it calls the AEInteractWithUser function. If AEInteractWithUser needs to post a notification request to bring your application to the front, your application yields the processor until the user brings your application to the front. To receive events while waiting for the user to bring your application to the front, you must provide an idle function.
  7922. If you provide a pointer to an idle function as a parameter to the AEInteractWithUser function, AEInteractWithUser calls your idle function whenever an update event, null event, operating-system event, or activate event is received for your application.
  7923. An idle function must use this syntax:
  7924. FUNCTION MyIdleFunction (VAR event: EventRecord;
  7925.                                  VAR sleepTime: LongInt;
  7926.                                  VAR mouseRgn: RgnHandle): Boolean;
  7927. The event parameter is the event record of the event to process. The sleepTime parameter and mouseRgn parameter are values that your idle function sets the first time it is called; thereafter they contain the values your function set. Your idle function should return a Boolean value that indicates whether your application wishes to continue waiting. Set the function result to TRUE if your application is no longer willing to wait for a reply from the server or for the user to bring the application to the front. Set the function result to FALSE if your application is still willing to wait.
  7928. You use the sleepTime and mouseRgn parameters in the same way as the sleep and mouseRgn parameters of the WaitNextEvent function. Specify in the sleepTime parameter the amount of time (in ticks) during which your application agrees to relinquish the processor if no events are pending for it. 
  7929. In the mouseRgn parameter, you specify a screen region that determines the conditions under which your application is to receive notice of mouse-moved events. Your idle function receives mouse-moved events only if your application is the front application and the cursor strays outside the region you specify.
  7930. Your idle function receives only update events, null events, operating-system events, and activate events. When your idle function receives a null event, it can use the idle time to update a status dialog box, animate cursors, or perform similar tasks. If your idle function receives any of the other events, it should handle the event as it normally would if received in its event loop.
  7931. Listing 5-5 shows an example of an idle function for use with AESend or AEInteractWithUser. The idle function processes update events, null events, operating-system events, and activate events. The first time the function is called it receives a null event. At this time, it sets the sleepTime and mouseRgn parameters. The function continues to process events until the server finishes handling the Apple event or the user brings the application to the front.
  7932. Your application should implement a method of checking whether the user wants to cancel. The MyCancelInQueue function in Listing 5-5 checks the event queue for any instances of Command-period and immediately returns TRUE as its function result if it finds a request to cancel in the event queue.
  7933. Listing 5-5    An idle function
  7934.  
  7935. FUNCTION MyIdleFunction (VAR event: EventRecord;
  7936.                                   VAR sleeptime: LongInt;
  7937.                                   VAR mouseRgn: RgnHandle): Boolean;
  7938. BEGIN
  7939.     MyIdleFunction := FALSE;
  7940.     {the MyCancelInQueue function checks for Command-period}
  7941.     IF MyCancelInQueue THEN
  7942.         BEGIN                            
  7943.             MyIdleFunction := TRUE;
  7944.             Exit(MyIdleFunction);
  7945.         END;
  7946.     CASE event.what OF
  7947.         updateEvt,
  7948.         activateEvt,                    {every idle function should handle }
  7949.         osEvt:                    { these kinds of events}
  7950.             BEGIN
  7951.                 MyAdjustCursor(event.where, gCursorRgn);    
  7952.                 DoEvent(event);
  7953.             END;
  7954.         nullEvent:
  7955.             BEGIN
  7956.                 {set the sleepTime and mouseRgn parameters}
  7957.                 mouseRgn := gCursorRgn;
  7958.                 sleeptime := 10;                        {use the correct value for your }
  7959.                                         { app}                            
  7960.                 DoIdle;                        {the application's idle handling}
  7961.             END;
  7962.     END; {of CASE}
  7963. END;
  7964. Writing a Reply Filter Function
  7965.  
  7966. If your application calls AESend and chooses to yield the processor to other processes while waiting for a reply, you can provide an idle function to process update, null, operating-system, and activate events, and you can provide a reply filter function to process high-level events. The previous section describes how an idle function processes events.
  7967. Your reply filter function can process any high-level events that it is willing to handle while waiting for a reply Apple event. For example, your application can choose to handle Apple events from other processes while waiting. Note, however, that your application must maintain any necessary state information. Your reply filter function must not accept any Apple events that can change the state of your application and make it impossible to return to its previous state.
  7968. A reply filter function must use this syntax:
  7969. FUNCTION MyReplyFilter (VAR event: EventRecord;
  7970.                                    returnID: LongInt; 
  7971.                                 transactionID: LongInt;
  7972.                                 sender: AEAddressDesc): Boolean;
  7973. The event parameter is the event record for a high-level event. The next three parameters contain valid information only if the event is an Apple event. The returnID parameter is the return ID for the Apple event. The transactionID parameter is the transaction ID for the Apple event. The sender parameter contains the address of the application or process that sent the Apple event.
  7974. Your reply filter function should return TRUE as the function result if you want to accept the Apple event; otherwise, it should return FALSE. If your filter function returns TRUE, the Apple Event Manager calls the AEProcessAppleEvent function on behalf of your application, and your handler routine is called to process the Apple event. In this case, make sure your handler is not called while it is still being used by an earlier call.
  7975.  
  7976. Reference to Creating and Sending Apple Events
  7977.  
  7978. This section describes the basic Apple Event Manager routines that your application can use to create and send Apple events. It also describes application-defined idle functions and reply filter functions that your application can provide for use by the Apple Event Manager. 
  7979. For information about data structures used with the routines described in this chapter, see the section “Data Structures Used by the Apple Event Manager,” which begins on page 4-56. 
  7980. Routines for Creating and Sending Apple Events
  7981.  
  7982. This section describes the Apple Event Manager routines you can use to create Apple events, create and duplicate descriptor records, create and add items to descriptor lists and AE records, add parameters and attributes to Apple events, and send Apple events. The section “Routines for Responding to Apple Events,” which begins on page 4-61, describes other Apple Event Manager routines used for both responding to and creating Apple events. 
  7983. Creating Apple Events
  7984.  
  7985. The AECreateAppleEvent function allows you to create an Apple event. 
  7986. AECreateAppleEvent
  7987.  
  7988. You can use the AECreateAppleEvent function to create an Apple event with several important attributes but no parameters. You add parameters to the Apple event after you create it.
  7989. FUNCTION AECreateAppleEvent (theAEEventClass: AEEventClass; 
  7990.                                       theAEEventID: AEEventID; 
  7991.                                       target: AEAddressDesc; 
  7992.                                       returnID: Integer; 
  7993.                                       transactionID: LongInt; 
  7994.                                       VAR result: AppleEvent): OSErr;
  7995. theAEEventClass 
  7996. The event class of the Apple event to be created.
  7997. theAEEventID 
  7998. The event ID of the Apple event to be created.
  7999. target     The address of the server application. 
  8000. returnID    The return ID for the Apple event; if you specify kAutoGenerateReturnID, the Apple Event Manager assigns a return ID that is unique to the current session.
  8001. transactionID
  8002. The transaction ID for this Apple event. A transaction is a sequence of Apple events that are sent back and forth between the client and server applications, beginning with the client’s initial request for a service. All Apple events that are part of a transaction must have the same transaction ID.
  8003. result     The AECreateAppleEvent function returns, in this parameter, the Apple event that it creates.
  8004. DESCRIPTION
  8005. The AECreateAppleEvent function creates an Apple event.Your application is responsible for using the AEDisposeDesc function to dispose of the Apple event when you no longer need it.
  8006. If AECreateAppleEvent returns a nonzero result code, it returns a null descriptor record unless the Apple Event Manager is not available because of limited memory. 
  8007. RESULT CODESnoErr    0    No error    
  8008. memFullErr    –108    Not enough room in heap zone    
  8009.  
  8010. SEE ALSO
  8011. See “Creating an Apple Event,” which begins on page 5-3, for more information on how to create an Apple event.
  8012. See “Specifying a Target Address” on page 5-10 for information on how to address an Apple event. 
  8013. Creating and Duplicating Descriptor Records
  8014.  
  8015. The AECreateDesc function converts data into a descriptor record, and the AEDuplicateDesc function makes a copy of a descriptor record.
  8016. AECreateDesc
  8017.  
  8018. You can use the AECreateDesc function to convert data into a descriptor record.
  8019. FUNCTION AECreateDesc (typeCode: DescType; dataPtr: Ptr; 
  8020.                               dataSize:             Size; VAR result: AEDesc): OSErr;
  8021. typeCode    The descriptor type for the descriptor record.
  8022. dataPtr    A pointer to the data for the descriptor record.
  8023. dataSize     The length, in bytes, of the data for the descriptor record.
  8024. result    The descriptor record that the AECreateDesc function creates. 
  8025. DESCRIPTION
  8026. The AECreateDesc function creates a new descriptor record that incorporates the specified data. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record when you no longer need it. You normally do this after receiving a result code from the AESend function.
  8027. If AECreateDesc returns a nonzero result code, it returns a null descriptor record unless the Apple Event Manager is not available because of limited memory. 
  8028. RESULT CODESnoErr    0    No error    
  8029. memFullErr    –108    Not enough room in heap zone    
  8030.  
  8031. SEE ALSO
  8032. For examples of the use of AECreateDesc, see “Adding Parameters to an Apple Event,” which begins on page 5-5, and Listing 5-2 on page 5-11.
  8033. AEDuplicateDesc
  8034.  
  8035. You can use the AEDuplicateDesc function to make a copy of a descriptor record.
  8036. FUNCTION AEDuplicateDesc (theAEDesc: AEDesc;
  8037.                                   VAR result: AEDesc): OSErr;
  8038. theAEDesc     The descriptor record to be duplicated.
  8039. result    The duplicate descriptor record. 
  8040. DESCRIPTION
  8041. The AEDuplicateDesc function creates a new descriptor record by copying the descriptor record from the parameter theAEDesc. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record when you no longer need it. You normally do this after receiving a result code from the AESend function.
  8042. If AEDuplicateDesc returns a nonzero result code, it returns a null descriptor record unless the Apple Event Manager is not available because of limited memory. 
  8043. It is common for applications to send Apple events that have one or more attributes or parameters in common. For example, if you send a series of Apple events to the same application, the address attribute is the same. In these cases, the most efficient way to create the necessary Apple events is to make a template Apple event that you can then copy—by calling the AEDuplicateDesc function—as needed. You then fill in or change the remaining parameters and attributes of the copy, send the copy by calling AESend, and dispose of the copy—by calling AEDisposeDesc—after AESend returns a result code.
  8044. RESULT CODESnoErr    0    No error    
  8045. memFullErr    –108    Not enough room in heap zone    
  8046.  
  8047. Creating Descriptor Lists and AE Records
  8048.  
  8049. The AECreateList function allows you to create an empty descriptor list or AE record.
  8050. AECreateList
  8051.  
  8052. You can use the AECreateList function to create an empty descriptor list or AE record.
  8053. FUNCTION AECreateList (factoringPtr: Ptr; factoredSize: Size;
  8054.                               isRecord: Boolean; 
  8055.                               VAR resultList: AEDescList): OSErr;
  8056. factoringPtr 
  8057. A pointer to the data at the beginning of each descriptor that is the same for all descriptor records in the list. If there is no common data, or if you decide not to isolate the common data, specify NIL as the value of this parameter.
  8058. factoredSize
  8059. The size of the common data. If there is no common data, or if you decide not to isolate the common data, the value of factoredSize must be 0. (See the description that follows for more information.)
  8060. isRecord     A Boolean value that specifies the kind of list to create. If you set it to TRUE, the Apple Event Manager creates an AE record. If you set it to FALSE, the Apple Event Manager creates a descriptor list.
  8061. resultList
  8062. The descriptor list or AE record that the AECreateList function creates. 
  8063. DESCRIPTION
  8064. The AECreateList function creates an empty descriptor list or AE record. Your application is responsible for using the AEDisposeDesc function to dispose of the resulting descriptor record when you no longer need it. You normally do this after receiving a result code from the AESend function.
  8065. If you intend to use a descriptor list for a factored Apple event array, you must provide, in the factoringPtr parameter, a pointer to the data shared by all items in the array and, in the factoredSize parameter, the size of the common data. The common data must be 4, 8, or more than 8 bytes in length because it always consists of (a) the descriptor type (4 bytes); (b) the descriptor type (4 bytes) and the size of each item’s data (4 bytes); or (c) the descriptor type (4 bytes), the size of each item’s data (4 bytes), and some portion of the data itself (1 or more bytes).
  8066. If AECreateList returns a nonzero result code, it returns a null descriptor record unless the Apple Event Manager is not available because of limited memory. 
  8067. RESULT CODESnoErr    0    No error    
  8068. paramErr    –50    Parameter error (value of handler pointer is NIL or odd)    
  8069. memFullErr    –108    Not enough room in heap zone    
  8070.  
  8071. SEE ALSO
  8072. For an example of the use of AECreateList, see Listing 5-1 on page 5-9.
  8073. For information about data types used with Apple event arrays, see “Apple Event Array Data Types” on page 4-60.
  8074. Adding Items to Descriptor Lists
  8075.  
  8076. The Apple Event Manager provides three routines that allow you to add descriptor records to any descriptor list, including an Apple event record. The AEPutPtr function converts data specified in a buffer to a descriptor record and adds the descriptor record to a descriptor list. The AEPutDesc function adds a descriptor record to a descriptor list. The AEPutArray function puts the data for an Apple event array into a descriptor list. 
  8077. AEPutPtr
  8078.  
  8079. You can use the AEPutPtr routine to add data specified in a buffer to any descriptor list as a descriptor record.
  8080. FUNCTION AEPutPtr (theAEDescList: AEDescList; index: LongInt;
  8081.                          typeCode: DescType; dataPtr: Ptr; 
  8082.                          dataSize: Size): OSErr;
  8083. theAEDescList
  8084. The descriptor list to which to add a descriptor record.
  8085. index     The position of the descriptor record in the descriptor list. (For example, the value 2 specifies the second descriptor record in the list.) If there is already a descriptor record in the specified position, it is replaced. If the value of index is 0, the descriptor record is added to the end of the list.
  8086. typeCode    The descriptor type for the resulting descriptor record.
  8087. dataPtr     A pointer to the data for the descriptor record.
  8088. dataSize    The length, in bytes, of the data for the descriptor record.
  8089. RESULT CODESnoErr    0    No error    
  8090. memFullErr    –108    Not enough room in heap zone    
  8091. errAEWrongDataType    –1703    Wrong descriptor type    
  8092. errAENotAEDesc    –1704    Not a valid descriptor record    
  8093. errAEBadListItem    –1705    Operation involving a list item failed    
  8094. errAEIllegalIndex    –1719    Not a valid list index    
  8095.  
  8096. SEE ALSO
  8097. For an example of the use of AEPutPtr, see Listing 5-1 on page 5-9.
  8098. AEPutDesc
  8099.  
  8100. You can use the AEPutDesc function to add a descriptor record to any descriptor list.
  8101. FUNCTION AEPutDesc (theAEDescList: AEDescList; index: LongInt; 
  8102.                           theAEDesc: AEDesc): OSErr;
  8103. theAEDescList
  8104. The descriptor list to which to add a descriptor record.
  8105. index     The position of the descriptor record in the descriptor list. (For example, the value 2 specifies the second descriptor record in the list.) If there is already a descriptor record in the specified position, it is replaced. If the value of index is 0, the descriptor record is added to the end of the list.
  8106. theAEDesc     The descriptor record to be added to the list.
  8107. RESULT CODESnoErr    0    No error    
  8108. memFullErr    –108    Not enough room in heap zone    
  8109. errAEWrongDataType    –1703    Wrong descriptor type    
  8110. errAENotAEDesc    –1704    Not a valid descriptor record    
  8111. errAEBadListItem    –1705    Operation involving a list item failed    
  8112. errAEIllegalIndex    –1719    Not a valid list index    
  8113.  
  8114. AEPutArray
  8115.  
  8116. You can use the AEPutArray function to put the data for an Apple event array into any descriptor list.
  8117. FUNCTION AEPutArray (theAEDescList: AEDescList; 
  8118.                             arrayType: AEArrayType; 
  8119.                              arrayPtr: AEArrayDataPointer; 
  8120.                             itemType: DescType; 
  8121.                              itemSize: Size; itemCount: LongInt): OSErr;
  8122. theAEDescList
  8123. The descriptor list into which to put the Apple event array. If there are any items already in the descriptor list, they are replaced.
  8124. arrayType    The Apple event array type to be created. This is specified by one of the following constants: kAEDataArray, kAEPackedArray, kAEHandleArray, kAEDescArray, or kAEKeyDescArray. 
  8125. arrayPtr     A pointer to the buffer containing the array.
  8126. itemType     For arrays of type kAEDataArray, kAEPackedArray, or kAEHandleArray, the descriptor type of array items to be created. 
  8127. itemSize     For arrays of type kAEDataArray or kAEPackedArray, the size (in bytes) of the array items to be created.
  8128. itemCount     The number of elements in the array.
  8129. DESCRIPTION
  8130. When you use AEPutArray to put an array into a factored descriptor list, each array item must include the data that is common to all the descriptor records in the list. The Apple Event Manager automatically isolates the data you specified in the call to AECreateList that is common to all the elements of the array.
  8131. RESULT CODESnoErr    0    No error    
  8132. memFullErr    –108    Not enough room in heap zone    
  8133. errAEWrongDataType    –1703    Wrong descriptor type    
  8134. errAENotAEDesc    –1704    Not a valid descriptor record    
  8135.  
  8136. SEE ALSO
  8137. For information about data types and constants used with AEPutArray, see “Apple Event Array Data Types” on page 4-60.
  8138. For more information about creating descriptor lists for Apple event arrays, see the description of AECreateList on page 5-28. 
  8139. Adding Data and Descriptor Records to AE Records
  8140.  
  8141. The Apple Event Manager provides two routines that allow you to add data and descriptor records to AE records. The AEPutKeyPtr function takes a pointer to data, a descriptor type, and a keyword and converts them into a keyword-specified descriptor record that it adds to an AE record. The AEPutKeyDesc function takes a descriptor record and a keyword and converts them into a keyword-specified descriptor record that it adds to an AE record.   
  8142. AEPutKeyPtr
  8143.  
  8144. You can use the AEPutKeyPtr function to add a pointer to data, a descriptor type, and a keyword to an AE record as a keyword-specified descriptor record. 
  8145. FUNCTION AEPutKeyPtr (theAERecord: AERecord; 
  8146.                              theAEKeyword: AEKeyword; 
  8147.                              typeCode: DescType; dataPtr: Ptr; 
  8148.                              dataSize: Size): OSErr;
  8149. theAERecord
  8150. The AE record to which to add a keyword-specified 
  8151. descriptor record.
  8152. theAEKeyword
  8153. The keyword that identifies the descriptor record. If the AE record already includes a descriptor record with this keyword, it is replaced.
  8154. typeCode     The descriptor type for the keyword-specified descriptor record.
  8155. dataPtr     A pointer to the data for the keyword-specified descriptor record.
  8156. dataSize     The length, in bytes, of the data for the keyword-specified descriptor record.
  8157. RESULT CODESnoErr    0    No error    
  8158. memFullErr    –108    Not enough room in heap zone    
  8159. errAEWrongDataType    –1703    Wrong descriptor type    
  8160. errAENotAEDesc    –1704    Not a valid descriptor record    
  8161. errAEBadListItem    –1705    Operation involving a list item failed    
  8162.  
  8163. AEPutKeyDesc
  8164.  
  8165. You can use the AEPutKeyDesc function to add a descriptor record and a keyword to an AE record as a keyword-specified descriptor record. 
  8166. FUNCTION AEPutKeyDesc (theAERecord: AERecord; 
  8167.                               theAEKeyword: AEKeyword; 
  8168.                               theAEDesc: AEDesc): OSErr;
  8169. theAERecord 
  8170. The AE record to which to add the keyword-specified descriptor record.
  8171. theAEKeyword 
  8172. The keyword specifying the descriptor record. If there was already a keyword-specified descriptor record with this keyword, it is replaced.
  8173. theAEDesc     The descriptor record for the keyword-specified descriptor record.
  8174. RESULT CODESnoErr    0    No error    
  8175. memFullErr    –108    Not enough room in heap zone    
  8176. errAEWrongDataType    –1703    Wrong descriptor type    
  8177. errAENotAEDesc    –1704    Not a valid descriptor record    
  8178. errAEBadListItem    –1705    Operation involving a list item failed    
  8179.  
  8180. Adding Parameters and Attributes to Apple Events
  8181.  
  8182. The Apple Event Manager provides four functions that allow you to add Apple event parameters and attributes to an Apple event. The AEPutParamPtr and AEPutParamDesc functions add parameters to a specified Apple event. The AEPutAttributePtr and AEPutAttributeDesc functions add attributes to a specified Apple event.
  8183. AEPutParamPtr
  8184.  
  8185. You can use the AEPutParamPtr function to add a pointer to data, a descriptor type, and a keyword to an Apple event as an Apple event parameter.
  8186. FUNCTION AEPutParamPtr (theAppleEvent: AppleEvent; 
  8187.                                 theAEKeyword: AEKeyword; 
  8188.                                 typeCode: DescType; dataPtr: Ptr; 
  8189.                                 dataSize: Size): OSErr;
  8190. theAppleEvent
  8191. The Apple event to which to add a parameter.
  8192. theAEKeyword
  8193. The keyword for the parameter to be added. If the Apple event already included a parameter with this keyword, the parameter is replaced.
  8194. typeCode    The descriptor type for the parameter.
  8195. dataPtr    A pointer to the data for the parameter.
  8196. dataSize    The length, in bytes, of the data for the parameter.
  8197. RESULT CODESnoErr    0    No error    
  8198. memFullErr    –108    Not enough room in heap zone    
  8199. errAEWrongDataType    –1703    Wrong descriptor type    
  8200. errAENotAEDesc    –1704    Not a valid descriptor record    
  8201. errAEBadListItem    –1705    Operation involving a list item failed    
  8202.  
  8203. SEE ALSO
  8204. For an example of the use of AEPutParamPtr, see “Adding Parameters to an Apple Event,” which begins on page 5-5.
  8205. AEPutParamDesc
  8206.  
  8207. You can use the AEPutParamDesc function to add a descriptor record and a keyword to an Apple event as an Apple event parameter.
  8208. FUNCTION AEPutParamDesc (theAppleEvent: AppleEvent; 
  8209.                                  theAEKeyword: AEKeyword; 
  8210.                                  theAEDesc: AEDesc): OSErr;
  8211. theAppleEvent
  8212. The Apple event to which to add a parameter.
  8213. theAEKeyword
  8214. The keyword for the parameter to be added. If the Apple event already included a parameter with this keyword, the parameter is replaced.
  8215. theAEDesc     The descriptor record for the parameter.
  8216. RESULT CODESnoErr    0    No error    
  8217. memFullErr    –108    Not enough room in heap zone    
  8218. errAEWrongDataType    –1703    Wrong descriptor type    
  8219. errAENotAEDesc    –1704    Not a valid descriptor record    
  8220. errAEBadListItem    –1705    Operation involving a list item failed    
  8221.  
  8222. SEE ALSO
  8223. For an example of the use of AEPutParamDesc, see “Adding Parameters to an Apple Event,” which begins on page 5-5.
  8224. AEPutAttributePtr
  8225.  
  8226. You can use the AEPutAttributePtr function to add a pointer to data, a descriptor type, and a keyword to an Apple event as an attribute.
  8227. FUNCTION AEPutAttributePtr (theAppleEvent: AppleEvent;
  8228.                                      theAEKeyword: AEKeyword; 
  8229.                                      typeCode: DescType; 
  8230.                                      dataPtr: Ptr; dataSize: Size): OSErr;
  8231. theAppleEvent 
  8232. The Apple event to which to add an attribute.
  8233. theAEKeyword
  8234. The keyword for the attribute to be added. 
  8235.     TYPE AEKeyword = PACKED ARRAY[1..4] OF Char;
  8236.     The keyword can be any of the constants listed in the description that follows. If the Apple event already included an attribute with this keyword, the attribute is replaced. 
  8237. typeCode    The descriptor type for the attribute.
  8238. dataPtr     A pointer to the buffer containing the data to be assigned to the attribute.
  8239. dataSize    The length, in bytes, of the data to be assigned to the attribute.
  8240. DESCRIPTION
  8241. The AEPutAttributePtr function adds the specified pointer to data, descriptor type, and keyword to the specified Apple event as an attribute. You can specify the parameter theAEKeyWord using any of the following constants:
  8242. CONST
  8243.     keyAddressAttr                                 = 'addr'; {address of target }
  8244.                                                  { application}
  8245.     keyEventClassAttr                                 = 'evcl'; {event class}
  8246.     keyEventIDAttr                                = 'evid'; {event ID}
  8247.     keyEventSourceAttr                                = 'esrc'; {source application}
  8248.     keyInteractLevelAttr                                = 'inte'; {settings to allow the }
  8249.                                                  { Apple Event Manager to }
  8250.                                                  { bring server application }
  8251.                                                  { to the foreground}
  8252.  
  8253.     keyMissedKeywordAttr                                = 'miss'; {first required parameter }
  8254.                                                  { remaining in Apple event}
  8255.     keyOptionalKeywordAttr                                = 'optk'; {list of optional }
  8256.                                                  { parameters for Apple }
  8257.                                                  { event}
  8258.     keyOriginalAddressAttr                                = 'from';             {address of original source }
  8259.                                                  { of Apple event}     
  8260.     keyReturnIDAttr                                 = 'rtid'; {return ID for reply Apple }
  8261.                                                  { event}
  8262.     keyTimeoutAttr                                = 'timo'; {length of time in ticks }
  8263.                                                  { that client will wait }
  8264.                                                  { for reply or result from } 
  8265.                                                  { the server}
  8266.     keyTransactionIDAttr                                = 'tran'; {transaction ID identifying }
  8267.                                                  { a series of Apple events}
  8268. RESULT CODESnoErr    0    No error    
  8269. memFullErr    –108    Not enough room in heap zone    
  8270. errAECoercionFail    –1700    Data could not be coerced to the requested descriptor type    
  8271. errAENotAEDesc    –1704    Not a valid descriptor record    
  8272.  
  8273. AEPutAttributeDesc
  8274.  
  8275. You can use the AEPutAttributeDesc function to add a descriptor record and a keyword to an Apple event as an attribute.
  8276. FUNCTION AEPutAttributeDesc (theAppleEvent: AppleEvent;
  8277.                                       theAEKeyword: AEKeyword; 
  8278.                                       theAEDesc: AEDesc): OSErr;
  8279. theAppleEvent
  8280. The Apple event to which you are adding an attribute.
  8281. theAEKeyword
  8282. The keyword for the attribute to be added. 
  8283.     TYPE AEKeyword = PACKED ARRAY[1..4] OF Char;
  8284.     The keyword can be any of the constants listed in the description of AEPutAttributePtr on page 5-35. If the Apple event already included an attribute with this keyword, the attribute is replaced. 
  8285. theAEDesc    The descriptor record to be assigned to the attribute. The descriptor type of the specified descriptor record should match the defined descriptor type for that attribute. For example, the keyEventSourceAttr attribute has the typeShortInteger descriptor type.
  8286. DESCRIPTION
  8287. The AEPutAttributeDesc function takes a descriptor record and a keyword and adds them to an Apple event as an attribute. If the descriptor type required for the attribute is different from the descriptor type of the descriptor record, the Apple Event Manager attempts to coerce the descriptor record into the required type, with one exception: the Apple Event Manager does not attempt to coerce the data for an address attribute, thereby allowing applications to use their own address types. 
  8288. RESULT CODESnoErr    0    No error    
  8289. memFullErr    –108    Not enough room in heap zone    
  8290. errAECoercionFail    –1700    Data could not be coerced to the requested descriptor type     
  8291. errAENotAEDesc    –1704    Not a valid descriptor record    
  8292.  
  8293. SEE ALSO
  8294. For an example of the use of AEPutAttributeDesc, see Listing 5-1 on page 5-9. 
  8295. Sending Apple Events
  8296.  
  8297. The AESend function allows you to send an Apple event that you have previously created with the AECreateAppleEvent function.  
  8298. AESend
  8299.  
  8300. You can use the AESend function to send an Apple event.
  8301. FUNCTION AESend (theAppleEvent: AppleEvent; 
  8302.                       VAR reply: AppleEvent; sendMode: AESendMode; 
  8303.                       sendPriority: AESendPriority; 
  8304.                       timeOutInTicks: LongInt; idleProc: IdleProcPtr; 
  8305.                       filterProc: EventFilterProcPtr): OSErr;
  8306. theAppleEvent 
  8307. The Apple event to be sent.
  8308. reply     The reply Apple event returned by the AESend function if you specify the kAEWaitReply flag in the sendMode parameter. (If you specify the kAEQueueReply flag in the sendMode parameter, you receive the reply Apple event in your event queue.) If you specify kAENoReply flag, the reply Apple event returned by this function is a null descriptor record. If you specify kAEWaitReply in the sendMode parameter, your application is responsible for using the AEDisposeDesc function to dispose of the descriptor record returned in the reply parameter.
  8309. sendMode    Specifies the following: the reply mode for the Apple event (set with one of the constants kAENoReply, kAEQueueReply, or kAEWaitReply); the interaction level (set with one of the constants kAENeverInteract, kAECanInteract, or kAEAlwaysInteract, which represent flags in the keyInteractLevelAttr attribute); the application switch mode (set with the kAECanSwitchLayer constant); the reconnection mode (set with the kAEDontReconnect constant); and the return receipt mode (set with the kAEWantReceipt constant). You obtain the value for this parameter by adding the appropriate constants. (The description that follows provides more details about the sendMode flags.)
  8310. sendPriority 
  8311. An integer of data type AESendPriority that specifies whether the Apple event is put at the back of the event queue (indicated by the kAENormalPriority flag) or at the front of the queue (indicated by the kAEHighPriority flag).  
  8312. timeOutInTicks 
  8313. If the reply mode specified in the sendMode parameter is kAEWaitReply, or if a return receipt is requested, this parameter specifies the length of time (in ticks) that the client application is willing to wait for the reply or return receipt from the server application before timing out. Most applications should use the kAEDefaultTimeout constant, which tells the Apple Event Manager to provide an appropriate timeout duration. If the value of this parameter is kNoTimeOut, the Apple event never times out.
  8314. idleProc     A pointer to a function that handles events (such as update, operating-system, activate, and null events) that your application receives while waiting for a reply. Your application can also perform other tasks (such as displaying a wristwatch or spinning beachball cursor) while waiting for a reply or a return receipt. Your application must provide an idle function if it specifies the kAEWaitReply flag in the sendMode parameter.
  8315. filterProc
  8316. A pointer to a function that accepts certain incoming Apple events that are received while the handler waits for a reply or a return receipt and filters out the rest.
  8317. DESCRIPTION
  8318. You can use one of the following flags in the sendMode parameter to specify the reply mode for an Apple event. Only one of these flags may be set.
  8319. Flag    Description    
  8320. kAENoReply    Your application does not want a reply Apple event; the server processes your Apple event as soon as it has the opportunity.    
  8321. kAEQueueReply    Your application wants a reply Apple event; the reply appears in your event queue as soon as the server has the opportunity to process and respond to your Apple event.    
  8322. kAEWaitReply    Your application wants a reply Apple event and is willing to give up the processor while waiting for the reply; for example, if the server application is on the same computer as your application, your application yields the processor to allow the server to respond to your Apple event. If you specify kAEWaitReply, you should provide an idle function.     
  8323.  
  8324. You can communicate your user interaction preferences to the server application by specifying one of the following flags in the sendMode parameter. Only one of these flags may be set.
  8325. Flag    Description    
  8326. kAENeverInteract    The server application should never interact with the user in response to the Apple event. If this flag is set, AEInteractWithUser returns the errAENoUserInteraction result code. This flag is the default when an Apple event is sent to a remote application.    
  8327. kAECanInteract    The server application can interact with the user in response to the Apple event—by convention, if the user needs to supply information to the server. If this flag is set and the server allows interaction, AEInteractWithUser either brings the server application to the foreground or posts a notification request. This flag is the default when an Apple event is sent to a local application.    
  8328. kAEAlwaysInteract    The server application can interact with the user in response to the Apple event—by convention, whenever the server application normally asks a user to confirm a decision or interact in any other way, even if no additional information is needed from the user. If this flag is set and the server allows interaction, AEInteractWithUser either brings the server application to the foreground or posts a notification request.    
  8329.  
  8330. The flags in the following list specify the application switch mode, the reconnection mode, and the return receipt mode. Any of these flags may be set.
  8331. Flag    Description    
  8332. kAECanSwitchLayer    If both the client and server allow interaction, and if the client application is the active application on the local computer and is waiting for a reply (that is, it has set the kAEWaitReply flag), AEInteractWithUser brings the server directly to the foreground. Otherwise, AEInteractWithUser uses the Notification Manager to request that the user bring the server application to the foreground.    
  8333. kAEDontReconnect    The Apple Event Manager must not automatically try to reconnect if it receives a sessClosedErr result code from the PPC Toolbox.    
  8334. kAEWantReceipt    The sender wants to receive a return receipt for this Apple event from the Event Manager. (A return receipt means only that the receiving application accepted the Apple event; the Apple event may or may not be handled successfully after it is accepted.) If the receiving application does not send a return receipt before the request times out, AESend returns errAETimeout as its function result.    
  8335.  
  8336. If the Apple Event Manager cannot find a handler for an Apple event in either the application or system Apple event dispatch table, it returns the result code errAEEventNotHandled to the server application (as the result of the AEProcessAppleEvent function). If the client application is waiting for a reply, the Apple Event Manager also returns this result code to the client.
  8337. The AESend function returns noErr as its function result if the Apple event was successfully sent by the Event Manager. A noErr result from AESend does not indicate that the Apple event was handled successfully; it indicates only that the Apple event was successfully sent by the Event Manager. If the handler returns a result code other than noErr, and if the client is waiting for a reply, it is returned in the keyErrorNumber parameter of the reply Apple event.
  8338. If your application is sending an event to itself, you can set one of these flags to prevent the event from being recorded or to ask the Apple Event Manager to record the event without your application actually receiving it. Only one of these flags may be set.
  8339. Flag    Description    
  8340. kAEDontRecord    Your application is sending an event to itself but does not want the event recorded. When Apple event recording is on, the Apple Event Manager records a copy of every event your application sends to itself except for those events for which this flag is set.     
  8341. kAEDontExecute    Your application is sending an Apple event to itself for recording purposes only—that is, you want the Apple Event Manager to send a copy of the event to the recording process but you do not want your application actually to receive the event.     
  8342.  
  8343. RESULT CODESnoErr    0    No error    
  8344. eLenErr    –92    Buffer too big to send    
  8345. memFullErr    –108    Not enough room in heap zone    
  8346. userCanceledErr    –128    User canceled an operation    
  8347. procNotFound    –600    No eligible process with specified process serial number    
  8348. connectionInvalid    –609    Nonexistent signature or session ID    
  8349. noUserInteractionAllowed    –610    Background application sends event requiring authentication    
  8350. noPortErr    –903    Client hasn’t set 'SIZE' resource to indicate awareness of high-level events    
  8351. destPortErr    –906    Server hasn’t set 'SIZE' resource to indicate awareness of high-level events, or else is not present    
  8352. sessClosedErr    –917    The kAEDontReconnect flag in the sendMode parameter was set and the server quit, then restarted    
  8353. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event handler    
  8354. errAEUnknownSendMode    –1710    Invalid sending mode was passed    
  8355. errAEWaitCanceled    –1711    User canceled out of wait loop for reply or receipt    
  8356. errAETimeout    –1712    Apple event timed out    
  8357. errAEUnknownAddressType    –1716    Unknown Apple event address type    
  8358.  
  8359. SEE ALSO
  8360. For more information on sending Apple events, see “Sending an Apple Event,” which begins on page 5-13.
  8361. For information on writing an idle function, see “Writing an Idle Function,” which begins on page 5-21.
  8362. For information on writing a reply filter function, see “Writing a Reply Filter Function,” which begins on page 5-24. 
  8363. For information on when to use the kAEDontExecute flag, see the chapter “Recording Apple Events” in this book.
  8364. Application-Defined Routines
  8365.  
  8366. If your application sends an Apple event using AESend and is waiting for a reply, or if it calls AEInteractWithUser, you can provide an idle function to handle update events, null events, operating-system events, and activate events. You can also provide a reply filter function that can handle any high-level events that you want your application to handle while it is waiting for a reply or for user interaction.
  8367. MyIdleFunction
  8368.  
  8369. An idle function has the following syntax:
  8370. FUNCTION MyIdleFunction (VAR event: EventRecord;
  8371.                                  VAR sleepTime:         LongInt;
  8372.                                  VAR mouseRgn: RgnHandle): Boolean;
  8373. event    The event record of the event to process.
  8374. sleepTime    Amount of time (in ticks) during which your application agrees to relinquish the processor if no events are pending.
  8375. mouseRgn    A screen region that determines the conditions under which your application is to receive notice of mouse-moved events. 
  8376. DESCRIPTION
  8377. If your application provides a pointer to an idle function (MyIdleFunction) as a parameter to AESend or AEInteractWithUser, the Apple Event Manager will call the idle function to handle any update event, null event, operating-system event, or activate event received for your application while it is waiting for a reply.
  8378. Set the function result to TRUE if your application is no longer willing to wait for a reply from the server or for the user to bring the application to the front. Set the function result to FALSE if your application is still willing to wait.
  8379. SEE ALSO
  8380. For more information, see “Writing an Idle Function,” which begins on page 5-21.
  8381. MyReplyFilter
  8382.  
  8383. A reply filter function has the following syntax: 
  8384. FUNCTION MyReplyFilter (VAR event: EventRecord;
  8385.                                 returnID: LongInt; 
  8386.                                 transactionID: LongInt;
  8387.                                 sender: AEAddressDesc): Boolean;
  8388. event    The event record for a high-level event. The next three parameters contain valid information only if the event is an Apple event.
  8389. returnID    Return ID for the Apple event.
  8390. transactionID
  8391. Transaction ID for the Apple event.
  8392. sender    Address of process that sent the Apple event.
  8393. DESCRIPTION
  8394. If your application provides a pointer to a reply filter function as a parameter to the AESend function, the reply filter function can process any high-level events that it is willing to handle while your application is waiting for a reply. 
  8395. Your reply filter function should return TRUE as the function result if you want to accept the Apple event; otherwise, it should return FALSE.
  8396. SEE ALSO
  8397. For more information, see “Writing a Reply Filter Function” on page 5-24. 
  8398.  
  8399.  
  8400. Summary of Creating and Sending Apple Events
  8401.  
  8402. Pascal Summary
  8403.  
  8404. Constants
  8405.  
  8406. CONST        
  8407.     gestaltAppleEventsAttr                                    = 'evnt';                {selector for Apple events}
  8408.     gestaltAppleEventsPresent                                    = 0;                {if this bit is set, then Apple }
  8409.                                                         { Event Manager is available}
  8410.  
  8411.     {Apple event descriptor types}
  8412.     typeBoolean                                = 'bool';                    {1-byte Boolean value}
  8413.     typeChar                                = 'TEXT';                    {unterminated string}
  8414.     typeSMInt                                = 'shor';                    {16-bit integer}
  8415.     typeInteger                                = 'long';                    {32-bit integer}
  8416.     typeSMFloat                                = 'sing';                    {SANE single}
  8417.     typeFloat                                = 'doub';                    {SANE double}
  8418.     typeLongInteger                                = 'long';                    {32-bit integer}
  8419.     typeShortInteger                                = 'shor';                    {16-bit integer}
  8420.     typeLongFloat                                = 'doub';                    {SANE double}
  8421.     typeShortFloat                                = 'sing';                    {SANE single}
  8422.     typeExtended                                = 'exte';                    {SANE extended}
  8423.     typeComp                                = 'comp';                    {SANE comp}
  8424.     typeMagnitude                                = 'magn';                    {unsigned 32-bit integer}
  8425.     typeAEList                                = 'list';                    {list of descriptor records}
  8426.     typeAERecord                                = 'reco';                    {list of keyword-specified }
  8427.                                                         { descriptor records}
  8428.     typeAppleEvent                                = 'aevt';                    {Apple event record}
  8429.     typeTrue                                = 'true';                    {TRUE Boolean value}
  8430.     typeFalse                                = 'fals';                    {FALSE Boolean value}
  8431.     typeAlias                                = 'alis';                    {alias record}
  8432.     typeEnumerated                                = 'enum';                    {enumerated data}
  8433.     typeType                                = 'type';                    {four-character code for }
  8434.                                                         { event class or event ID}
  8435.     typeAppParameters                                = 'appa';                    {Process Manager launch parameters}
  8436.     typeProperty                                = 'prop';                    {Apple event property}
  8437.     typeFSS                                = 'fss ';                    {file system specification}
  8438.     typeKeyword                                = 'keyw';                    {Apple event keyword}
  8439.     typeSectionH                                = 'sect';                    {handle to a section record}
  8440.     typeWildCard                                = '****';                    {matches any type}
  8441.     typeApplSignature                                = 'sign';                    {application signature}
  8442.     typeSessionID                                = 'ssid';                    {session reference number}
  8443.     typeTargetID                                = 'targ';                    {target ID record}
  8444.     typeProcessSerialNumber                                = 'psn ';                    {process serial number}
  8445.     typeNull                                = 'null';                    {NULL or nonexistent data}
  8446.     
  8447.     {keywords for Apple event parameters}
  8448.     keyDirectObject                                = '----';                    {direct parameter}
  8449.     keyErrorNumber                                = 'errn';                    {error number parameter}
  8450.     keyErrorString                                = 'errs';                    {error string parameter}
  8451.     keyProcessSerialNumber                                = 'psn ';                    {process serial number param}
  8452.  
  8453.     {keywords for Apple event attributes}
  8454.     keyTransactionIDAttr                                = 'tran';                    {transaction ID}
  8455.     keyReturnIDAttr                                = 'rtid';                    {return ID}
  8456.     keyEventClassAttr                                 = 'evcl';                    {event class}
  8457.     keyEventIDAttr                                = 'evid';                    {event ID}
  8458.     keyAddressAttr                                = 'addr';                    {address of target or }
  8459.                                                         { client application}
  8460.     keyOptionalKeywordAttr                                = 'optk';                    {list of optional parameters }
  8461.                                                         { for the Apple event}
  8462.     keyTimeoutAttr                                = 'timo';                    {number of ticks the client }
  8463.                                                         { will wait}
  8464.     keyInteractLevelAttr                                 = 'inte';                    {settings to allow Apple Event }
  8465.                                                         { Manager to bring server }                    
  8466.                                                         { to foreground}
  8467.     keyEventSourceAttr                                = 'esrc';                    {nature of source }
  8468.                                                         { application}
  8469.     keyMissedKeywordAttr                                = 'miss';                    {first required parameter }
  8470.                                                         { remaining in an Apple event}
  8471.     keyOriginalAddressAttr                                = 'from';                    {address of original source; }
  8472.                                                         { available only in version } 
  8473.                                                         { 1.01 and later versions of }
  8474.                                                         { the Apple Event Manager}
  8475.  
  8476.     {keywords for special handlers}
  8477.     keyPreDispatch                                = 'phac';                    {identifies a handler routine }
  8478.                                                         { called immediately before the }
  8479.                                                         { Apple Event Manager dispatches }
  8480.                                                         { an Apple event}
  8481.  
  8482.  
  8483.     keySelectProc                                = 'selh';                     {selector used with }
  8484.                                                         { AERemoveSpecialHandler to }
  8485.                                                         { disable the OSL}
  8486.  
  8487.     {keywords for use with AEManagerInfo; available only in version }
  8488.     { 1.0.1 and later versions of the Apple Event Manager}
  8489.     keyAERecorderCount                                 = 'recr';                    {keyword for recording info}
  8490.     keyAEVersion                                 = 'vers';                    {keyword for version info}
  8491.  
  8492.     {event class}
  8493.     kCoreEventClass                                = 'aevt';                    {event class for required Apple }
  8494.                                                         { events}
  8495.  
  8496.     {event IDs for required Apple events}
  8497.     kAEOpenApplication                                = 'oapp';                    {event ID for Open }
  8498.                                                         { Application event}
  8499.     kAEOpenDocuments                                = 'odoc';                    {event ID for Open Documents event}
  8500.     kAEPrintDocuments                                = 'pdoc';                    {event ID for Print Documents }
  8501.                                                         { event}
  8502.     kAEQuitApplication                                = 'quit';                    {event ID for Quit Application }
  8503.                                                         { event}
  8504.     kAEAnswer                                = 'ansr';                    {event ID for Apple event replies}
  8505.     kAEApplicationDied                                = 'obit';                    {event ID for Application Died }
  8506.                                                         { event}
  8507.  
  8508.     {constants for setting the sendMode parameter of AESend}
  8509.     kAENoReply                                = $00000001;                    {client doesn't want reply}
  8510.     kAEQueueReply                                = $00000002;                    {client wants server to }
  8511.                                                         { reply in event queue}
  8512.     kAEWaitReply                                = $00000003;                    {client wants a reply and }
  8513.                                                         { will give up processor}
  8514.     kAENeverInteract                                = $00000010;                    {server application should }
  8515.                                                         { not interact with user }
  8516.                                                         { for this Apple event}
  8517.     kAECanInteract                                = $00000020;                    {server may interact with }
  8518.                                                         { user for this Apple event }
  8519.                                                         { to supply information}
  8520.  
  8521.     kAEAlwaysInteract                                = $00000030;                    {server may interact with user }
  8522.                                                         { for this Apple event even if }
  8523.                                                         { no information is required}
  8524.     kAECanSwitchLayer                                = $00000040;                    {server should come directly }
  8525.                                                         { to foreground when appropriate}
  8526.     kAEDontReconnect                                = $00000080;                    {don't reconnect if there }
  8527.                                                         { is a PPC session closed error}
  8528.     kAEWantReceipt                                = nReturnReceipt; {client wants return }
  8529.                                                         { receipt}
  8530.     kAEDontRecord                                = $00001000            ;        {don't record this event}
  8531.     kAEDontExecute                                = $00002000;                    {don't excecute this event}
  8532.  
  8533.     {constants for setting the sendPriority parameter of AESend}
  8534.     kAENormalPriority                                = $00000000;                    {put event at back of }
  8535.                                                         { event queue}
  8536.     kAEHighPriority                                = nAttnMsg;                    {put event at front of }
  8537.                                                         { the event queue}
  8538.  
  8539.     {event IDs for recording events; available only in version 1.01 and }
  8540.     { later versions of the Apple Event Manager}
  8541.     kAEStartRecording                                = 'reca';                    {event ID for Start Recording }
  8542.                                                         { event}
  8543.     kAEStopRecording                                = 'recc';                    {event ID for Stop Recording }
  8544.                                                         { event}
  8545.     kAENotifyStartRecording                                = 'rec1';                    {event ID for Recording On event}
  8546.     kAENotifyStopRecording                                = 'rec0';                    {event ID for Recording Off event}
  8547.     kAENotifyRecording                                = 'recr';                    {event ID for Receive Recordable }
  8548.                                                         { Event event}
  8549.  
  8550.     {constant for the returnID parameter of AECreateAppleEvent}
  8551.     kAutoGenerateReturnID                                = -1;                    {tells Apple Event Manager to }
  8552.                                                         { generate a unique return ID}
  8553.  
  8554.     {constant for transaction IDs}
  8555.     kAnyTransactionID                                 = 0;                    {the Apple event is not }
  8556.                                                         { part of a transaction}
  8557.  
  8558.     {constants for timeout durations}
  8559.     kAEDefaultTimeout                                = -1;                    {use default timeout value}
  8560.     kNoTimeOut                                = -2;                    {never time out}
  8561.  
  8562.     {constants for the dispatcher parameter of AEResumeTheCurrentEvent}
  8563.     kAENoDispatch                                = 0;                    {don't redispatch the Apple event}
  8564.     kAEUseStandardDispatch                                = -1;                    {redispatch the Apple event }
  8565.                                                         { by using its entry in the }
  8566.                                                         { Apple event dispatch table}
  8567. Data Types
  8568.  
  8569. TYPE
  8570.     AEEventClass = 
  8571.         PACKED ARRAY[1..4] OF Char;                                                    {event class for a high-level }
  8572.                                                             { event}
  8573.     AEEventID = 
  8574.         PACKED ARRAY[1..4] OF Char;                                                    {event ID for a high-level }
  8575.                                                             { event}
  8576.  
  8577.     AEKeyword = 
  8578.         PACKED ARRAY[1..4] OF Char;                                                    {keyword for a descriptor }
  8579.                                                             { record}
  8580.  
  8581.     DescType                                    = ResType;                    {descriptor type}
  8582.  
  8583.     AEDesc =                                                         {descriptor record}
  8584.     RECORD        
  8585.         descriptorType:                                 DescType;                    {type of data being passed}
  8586.         dataHandle:                                 Handle;                    {handle to data being passed}
  8587.     END;
  8588.  
  8589.     AEKeyDesc =                                                         {keyword-specified }
  8590.     RECORD                                                        { descriptor record}
  8591.         descKey:                                AEKeyword;                    {keyword}
  8592.         descContent:                                AEDesc    ;                {descriptor record}
  8593.     END;
  8594.  
  8595.     AEAddressDesc                                    = AEDesc;                    {address descriptor record}
  8596.  
  8597.     AEDescList                                    = AEDesc;                    {list of descriptor records}
  8598.  
  8599.     AERecord                                    = AEDescList;                    {list of keyword-specified }
  8600.                                                             { descriptor records}
  8601.  
  8602.     AppleEvent                                    = AERecord;                    {list of attributes and }
  8603.                                                             { parameters necessary for }
  8604.                                                             { an Apple event}
  8605.     AESendMode                                    = LongInt;                    {flags that determine how }
  8606.                                                             { an Apple event is sent}
  8607.  
  8608.     AESendPriority                                    = Integer;                    {send priority of an Apple }
  8609.                                                             { event}
  8610.     AEInteractAllowed = (kAEInteractWithSelf, kAEInteractWithLocal,
  8611.                                  kAEInteractWithAll);                            {what processes may }
  8612.                                                             { interact with the user}
  8613.  
  8614.     AEEventSource = (kAEUnknownSource, kAEDirectCall, kAESameProcess,
  8615.                           kAELocalProcess, kAERemoteProcess);
  8616.                                                             {the source of an Apple }
  8617.                                                             { event}
  8618.  
  8619.     AEArrayType = (kAEDataArray, kAEPackedArray, kAEHandleArray, 
  8620.                        kAEDescArray, kAEKeyDescArray);
  8621.                                                             {type of an Apple event array}
  8622.     AEArrayData = 
  8623.     RECORD                                                        {data for an Apple event array}
  8624.         CASE AEArrayType OF
  8625.         kAEDataArray:
  8626.             (AEDataArray:     ARRAY[0..0] OF Integer);
  8627.         kAEPackedArray:
  8628.             (AEPackedArray:     Packed Array[0..0] OF Char);
  8629.         kAEHandleArray:
  8630.             (AEHandleArray:     Array[0..0] OF Handle);
  8631.         kAEDescArray:
  8632.             (AEDescArray:     Array[0..0] OF AEDesc);
  8633.         kAEKeyDescArray:
  8634.             (AEKeyDescArray:     Array[0..0] OF AEKeyDesc);
  8635.     END;
  8636.     
  8637.     AEArrayDataPointer = ^AEArrayData;
  8638.  
  8639.     EventHandlerProcPtr = ProcPtr;                                                        {pointer to an Apple event }
  8640.                                                             { handler}
  8641.     IdleProcPtr = ProcPtr;                                                        {pointer to an application's }
  8642.                                                             { idle function}
  8643.     EventFilterProcPtr = ProcPtr;                                                        {pointer to an application's }
  8644.                                                             { filter function}
  8645. Routines for Creating and Sending Apple Events
  8646.  
  8647. Creating Apple Events
  8648. FUNCTION AECreateAppleEvent    (theAEEventClass: AEEventClass; 
  8649. theAEEventID: AEEventID; 
  8650. target: AEAddressDesc; returnID: Integer; transactionID: LongInt; 
  8651. VAR result: AppleEvent): OSErr;
  8652. Creating and Duplicating Descriptor Records
  8653. FUNCTION AECreateDesc    (typeCode: DescType; dataPtr: Ptr; 
  8654. dataSize: Size; VAR result: AEDesc): OSErr;
  8655. FUNCTION AEDuplicateDesc    (theAEDesc: AEDesc; VAR result: AEDesc): OSErr;
  8656. Creating Descriptor Lists and AE Records
  8657. FUNCTION AECreateList    (factoringPtr: Ptr; factoredSize: Size; isRecord: Boolean; 
  8658. VAR resultList: AEDescList): OSErr;
  8659. Adding Items to Descriptor Lists
  8660. FUNCTION AEPutPtr    (theAEDescList: AEDescList; index: LongInt; typeCode: DescType; dataPtr: Ptr; 
  8661. dataSize: Size): OSErr;
  8662. FUNCTION AEPutDesc    (theAEDescList: AEDescList; index: LongInt; theAEDesc: AEDesc): OSErr;
  8663. FUNCTION AEPutArray    (theAEDescList: AEDescList; 
  8664. arrayType: AEArrayType; 
  8665. arrayPtr: AEArrayDataPointer; 
  8666. itemType: DescType; itemSize: Size; 
  8667. itemCount: LongInt): OSErr;
  8668. Adding Data and Descriptor Records to AE Records
  8669. FUNCTION AEPutKeyPtr    (theAERecord: AERecord; 
  8670. theAEKeyword: AEKeyword; typeCode: DescType; dataPtr: Ptr; dataSize: Size): OSErr;
  8671. FUNCTION AEPutKeyDesc    (theAERecord: AERecord; 
  8672. theAEKeyword: AEKeyword; 
  8673. theAEDesc: AEDesc): OSErr;
  8674. Adding Parameters and Attributes to Apple Events
  8675. FUNCTION AEPutParamPtr    (theAppleEvent: AppleEvent; 
  8676. theAEKeyword: AEKeyword; typeCode: DescType; dataPtr: Ptr; dataSize: Size): OSErr;
  8677. FUNCTION AEPutParamDesc    (theAppleEvent: AppleEvent; 
  8678. theAEKeyword: AEKeyword; 
  8679. theAEDesc: AEDesc): OSErr;
  8680. FUNCTION AEPutAttributePtr    (theAppleEvent: AppleEvent; 
  8681. theAEKeyword: AEKeyword; typeCode: DescType; dataPtr: Ptr; dataSize: Size): OSErr;
  8682. FUNCTION AEPutAttributeDesc    (theAppleEvent: AppleEvent; 
  8683. theAEKeyword: AEKeyword; 
  8684. theAEDesc: AEDesc): OSErr;
  8685. Sending Apple Events
  8686. FUNCTION AESend    (theAppleEvent: AppleEvent; 
  8687. VAR reply: AppleEvent; sendMode: AESendMode; sendPriority: AESendPriority; 
  8688. timeOutInTicks: LongInt; 
  8689. idleProc: IdleProcPtr; 
  8690. filterProc: EventFilterProcPtr): OSErr;
  8691. Application-Defined Routines
  8692.  
  8693. FUNCTION MyIdleFunction    (VAR event: EventRecord;
  8694. VAR sleepTime: LongInt; 
  8695. VAR mouseRgn: RgnHandle): Boolean;
  8696. FUNCTION MyReplyFilter    (VAR event: EventRecord; 
  8697. returnID: LongInt; transactionID: LongInt; sender: AEAddressDesc): Boolean;
  8698. C Summary
  8699.  
  8700. Constants
  8701.  
  8702. enum {
  8703.         #define         gestaltAppleEventsAttr                                      'evnt'            /*selector for Apple events*/
  8704.         gestaltAppleEventsPresent                                             = 0        /*if this bit is set, then */
  8705.                                                             /* Apple Event Manager is */
  8706. };                                                            /* available*/
  8707.  
  8708.         /*Apple event descriptor types*/
  8709. enum        {
  8710.         typeBoolean                                = 'bool',                    /*1-byte Boolean value*/
  8711.         typeChar                                = 'TEXT',                    /*unterminated string*/
  8712.         typeSMInt                                = 'shor',                    /*16-bit integer*/
  8713.         typeInteger                                = 'long',                    /*32-bit integer*/
  8714.         typeSMFloat                                = 'sing',                    /*SANE single*/
  8715.         typeFloat                                = 'doub',                    /*SANE double*/
  8716.         typeLongInteger                                = 'long',                    /*32-bit integer*/
  8717.         typeShortInteger                                = 'shor',                    /*16-bit integer*/
  8718.         typeLongFloat                                = 'doub',                    /*SANE double*/
  8719.         typeShortFloat                                = 'sing',                    /*SANE single*/
  8720.         typeExtended                                = 'exte',                    /*SANE extended*/
  8721.         typeComp                                = 'comp',                    /*SANE comp*/
  8722.         typeMagnitude                                = 'magn',                    /*unsigned 32-bit integer*/
  8723.         typeAEList                                = 'list',                    /*list of descriptor records*/
  8724.         typeAERecord                                = 'reco',                    /*list of keyword-specified */
  8725.                                                             /* descriptor records*/
  8726.         typeAppleEvent                                = 'aevt',                    /*Apple event record*/
  8727.         typeTrue                                = 'true',                    /*TRUE Boolean value*/
  8728.         typeFalse                                = 'fals',                    /*FALSE Boolean value*/
  8729.         typeAlias                                = 'alis',                    /*alias record*/
  8730.         typeEnumerated                                = 'enum'                    /*enumerated data*/
  8731. };
  8732.  
  8733. enum {
  8734.         typeType                                = 'type',                    /*four-character code for */
  8735.                                                             /* event class or event ID*/
  8736.         typeAppParameters                                = 'appa',                    /*Process Manager launch */
  8737.                                                             /* parameters*/
  8738.         typeProperty                                = 'prop',                    /*Apple event property*/
  8739.         typeFSS                                = 'fss ',                    /*file system specification*/
  8740.         typeKeyword                                = 'keyw',                    /*Apple event keyword*/
  8741.  
  8742.         typeSectionH                                = 'sect',                    /*handle to a section record*/
  8743.         typeWildCard                                = '****',                    /*matches any type*/
  8744.         typeApplSignature                                = 'sign',                    /*application signature*/
  8745.         typeSessionID                                = 'ssid',                    /*session ID*/
  8746.         typeTargetID                                = 'targ',                    /*target ID record*/
  8747.         typeProcessSerialNumber                                = 'psn ',                    /*process serial number*/
  8748.         typeNull                                = 'null'                    /*NULL or nonexistent data*/
  8749. };
  8750.  
  8751.         /*keywords for Apple event parameters*/
  8752. enum     {
  8753.         keyDirectObject                                = '----',                    /*direct parameter*/
  8754.         keyErrorNumber                                = 'errn',                    /*error number parameter*/
  8755.         keyErrorString                                = 'errs',                    /*error string parameter*/
  8756.         keyProcessSerialNumber                                = 'psn '                    /*process serial number param*/
  8757. };
  8758.         /*keywords for Apple event attributes*/
  8759. enum     {
  8760.         keyTransactionIDAttr                                = 'tran',                    /*transaction ID*/
  8761.         keyReturnIDAttr                                = 'rtid',                    /*return ID*/
  8762.         keyEventClassAttr                                 = 'evcl',                    /*event class*/
  8763.         keyEventIDAttr                                = 'evid',                    /*event ID*/
  8764.         keyAddressAttr                                = 'addr',                    /*address of target or */
  8765.                                                             /* client application*/
  8766.         keyOptionalKeywordAttr                                = 'optk',                    /*list of optional parameters */
  8767.                                                             /* for the Apple event*/
  8768.         keyTimeoutAttr                                = 'timo',                    /*number of ticks the client */
  8769.                                                             /* will wait*/
  8770.         keyInteractLevelAttr                                 = 'inte',                    /*settings to allow Apple */
  8771.                                                             /* Event Mgr to bring */                    
  8772.                                                             /* server to foreground*/
  8773.         keyEventSourceAttr                                = 'esrc',                    /*nature of source */
  8774.                                                             /* application*/
  8775.         keyMissedKeywordAttr                                = 'miss',                    /*first required parameter */
  8776.                                                             /* remaining in an Apple */
  8777.                                                             /* event*/
  8778.         keyOriginalAddressAttr                                = 'from'                    /*address of original source; */
  8779.                                                             /* available only in version */ 
  8780.                                                             /* 1.01 and later versions of */
  8781.                                                             /* the Apple Event Manager*/
  8782. };
  8783.         
  8784.         /*keywords for special handlers*/
  8785. enum     {
  8786.         keyPreDispatch                                = 'phac',                    /*identifies a handler */
  8787.                                                             /* routine that is called */
  8788.                                                             /* immediately before the */
  8789.                                                             /* Apple Event Manager */
  8790.                                                             /* dispatches an Apple event*/
  8791.         keySelectProc                                = 'selh',                     /*selector used with */
  8792.                                                             /* AERemoveSpecialHandler to */
  8793.                                                             /* disable the OSL*/
  8794.         /*keywords for use with AEManagerInfo, available only in version */
  8795.         /* 1.0.1 and later versions of the Apple Event Manager*/
  8796.         keyAERecorderCount                                 = 'recr',                    /*keyword for recording info*/
  8797.         keyAEVersion                                 = 'vers',                    /*keyword for version info*/
  8798.  
  8799.         /*event class*/
  8800.         kCoreEventClass                                = 'aevt'                    /*event class for required */
  8801.                                                             /* Apple events*/
  8802. };
  8803.  
  8804.         /*event IDs for required Apple events*/
  8805. enum {
  8806.         kAEOpenApplication                                = 'oapp',                    /*event ID for Open */
  8807.                                                             /* Application event*/
  8808.         kAEOpenDocuments                                = 'odoc',                    /*event ID for Open */
  8809.                                                             /* Documents event*/
  8810.  
  8811.         kAEPrintDocuments                                = 'pdoc',                    /*event ID for Print */
  8812.                                                             /* Documents event*/
  8813.         kAEQuitApplication                                = 'quit',                    /*event ID for Quit */
  8814.                                                             /* Application event*/
  8815.         kAEAnswer                                = 'ansr',                    /*event ID for Apple event */
  8816.                                                             /* replies*/
  8817.         kAEApplicationDied                                = 'obit'                    /*event ID for Application */
  8818.                                                             /* Died event*/
  8819. };
  8820.         /*constants for setting the sendMode parameter of AESend*/
  8821. enum {
  8822.         kAENoReply                                = 0x00000001,                    /*client doesn't want reply*/
  8823.         kAEQueueReply                                = 0x00000002,                    /*client wants server to */
  8824.                                                             /* reply in event queue*/
  8825.         kAEWaitReply                                = 0x00000003,                    /*client wants a reply and */
  8826.                                                             /* will give up processor*/
  8827.         kAENeverInteract                                = 0x00000010,                    /*server application should */
  8828.                                                             /* not interact with user */
  8829.                                                             /* for this Apple event*/
  8830.         kAECanInteract                                = 0x00000020,                    /*server may interact with */
  8831.                                                             /* user for this Apple event */
  8832.                                                             /* to supply information*/
  8833.         kAEAlwaysInteract                                = 0x00000030,                    /*server may interact with */
  8834.                                                             /* user for this Apple event */
  8835.                                                             /* even if no information */
  8836.                                                             /* is required*/
  8837.         kAECanSwitchLayer                                = 0x00000040,                    /*server should come */
  8838.                                                             /* directly to foreground */
  8839.                                                             /* when appropriate*/
  8840.         kAEDontReconnect                                = 0x00000080,                    /*don't reconnect if there */
  8841.                                                             /* is a PPC session closed */
  8842.                                                             /* error*/
  8843.         kAEWantReceipt                                = nReturnReceipt, /*client wants return */
  8844.                                                             /* receipt*/
  8845.         kAEDontRecord                                = 0x00001000,                    /*don't record this event*/
  8846.         kAEDontExecute                                = 0x00002000,                    /*don't excecute this event*/
  8847.  
  8848.         /*constants for setting the sendPriority parameter of AESend*/
  8849.         kAENormalPriority                                = 0x00000000,                    /*post message at end of */
  8850.                                                             /* event queue*/
  8851.         kAEHighPriority                                = nAttnMsg                    /*post message at front of */
  8852.                                                             /* event queue*/
  8853. };
  8854.         /*event IDs for recording events; available only in version 1.01 and */
  8855.         /* later versions of the Apple Event Manager*/
  8856. enum {
  8857.         kAEStartRecording                                = 'reca'        ,            /*event ID for Start */
  8858.                                                             /* Recording event*/
  8859.         kAEStopRecording                                = 'recc',                    /*event ID for Stop */
  8860.                                                             /* Recording event*/
  8861.         kAENotifyStartRecording                                = 'rec1',                    /*event ID for Recording On */
  8862.                                                             /* event*/
  8863.         kAENotifyStopRecording                                = 'rec0',                    /*event ID for Recording Off */
  8864.                                                             /* event*/
  8865.         kAENotifyRecording                                = 'recr'                    /*event ID for Receive */
  8866.                                                             /* Recordable Event event*/
  8867. };
  8868. enum {
  8869.         /*constant for the returnID parameter of AECreateAppleEvent*/
  8870.         kAutoGenerateReturnID                                = -1,                    /*tells Apple Event Manager */
  8871.                                                             /* to generate a unique */
  8872.                                                             /* return ID*/
  8873.         /*constant for transaction IDs*/
  8874.         kAnyTransactionID                                 = 0,                    /*the Apple event is not */
  8875.                                                             /* part of a transaction*/
  8876.  
  8877.         /*constants for timeout durations*/
  8878.         kAEDefaultTimeout                                = -1,                    /*use default timeout value*/
  8879.         kNoTimeOut                                = -2    ,                /*never time out*/
  8880.         /*constants for the dispatcher parameter of AEResumeTheCurrentEvent*/
  8881.         kAENoDispatch                                = 0,                    /*don't redispatch the */
  8882.                                                             /* Apple event*/
  8883.         kAEUseStandardDispatch                                = -1                /*redispatch the Apple event */
  8884.                                                             /* by using its entry in the */
  8885.                                                             /* Apple event dispatch table*/
  8886. };
  8887. Data Types
  8888.  
  8889. typedef unsigned long AEEventClass;                                                            /*event class for a */
  8890.                                                             /* high-level event*/
  8891. typedef unsigned long AEEventID;                                                            /*event ID for a high-level */
  8892.                                                             /* event*/
  8893. typedef unsigned long AEKeyword;                                                            /*keyword for a descriptor */
  8894.                                                             /* record*/
  8895. typedef ResType DescType                                ;                            /*descriptor type*/
  8896.  
  8897. struct AEDesc {                                                             /*descriptor record*/
  8898.     DescType descriptorType;                                                         /*type of data being passed*/
  8899.     Handle dataHandle;                                                        /*handle to data being passed*/
  8900. };
  8901. typedef struct AEDesc AEDesc;
  8902.  
  8903. struct AEKeyDesc {                                                             /*keyword-specified */
  8904.                                                             /* descriptor record*/
  8905.     AEKeyword descKey;                                                        /*keyword*/
  8906.     AEDesc descContent;                                                        /*descriptor record*/
  8907. };
  8908. typedef struct AEKeyDesc AEKeyDesc;
  8909.  
  8910. typedef AEDesc AEAddressDesc;                                                            /*address descriptor record*/
  8911. typedef AEDesc AEDescList;                                                            /*list of descriptor records*/
  8912. typedef AEDescList AERecord;                                                            /*list of keyword-specified */
  8913.                                                             /* descriptor records*/
  8914. typedef AERecord AppleEvent;                                                            /*list of attributes and */
  8915.                                                             /* parameters necessary for */
  8916.                                                             /* an Apple event*/
  8917. typedef long AESendMode;                                                            /*flags that determine how */
  8918.                                                             /* an Apple event is sent*/
  8919.  
  8920.  
  8921.  
  8922. typedef short AESendPriority;                                                            /*send priority of an Apple */
  8923.                                                             /* event*/
  8924.  
  8925. enum { kAEInteractWithSelf, kAEInteractWithLocal,
  8926.          kAEInteractWithAll };                                                    /*what processes may */
  8927. typedef unsigned char AEInteractAllowed;                                                            /* interact with the user*/
  8928.  
  8929. enum { kAEUnknownSource, kAEDirectCall, kAESameProcess,             kAELocalProcess, 
  8930.          kAERemoteProcess };                                                    /*the source of an Apple */
  8931. typedef unsigned char AEEventSource;                                                            /* event*/
  8932. enum { kAEDataArray, kAEPackedArray, kAEHandleArray, 
  8933.          kAEDescArray, kAEKeyDescArray };                                                    /*type of an Apple event */
  8934. typedef unsigned char AEArrayType;                                                            /* array*/
  8935.  
  8936. union     AEArrayData {                                                         /*data for an Apple event */
  8937.     short         kAEDataArray[1];                                                /* array*/
  8938.     char     kAEPackedArray[1];
  8939.     Handle         kAEHandleArray[1];
  8940.     AEDesc         kAEDescArray[1];
  8941.     AEKeyDesc kAEKeyDescArray[1];
  8942. };
  8943. typedef union AEArrayData AEArrayData;
  8944.  
  8945. typedef AEArrayData *AEArrayDataPointer;
  8946.  
  8947. typedef ProcPtr EventHandlerProcPtr;                                                            /*pointer to an Apple event */
  8948.                                                             /* handler*/
  8949. typedef ProcPtr IdleProcPtr;                                                            /*pointer to an application's */
  8950.                                                             /* idle function*/
  8951. typedef ProcPtr EventFilterProcPtr;                                                            /*pointer to an application's */
  8952.                                                             /* filter function*/
  8953. Routines for Creating and Sending Apple Events
  8954.  
  8955. Creating Apple Events
  8956. pascal OSErr AECreateAppleEvent
  8957. (AEEventClass theAEEventClass, 
  8958. AEEventID theAEEventID, 
  8959. const AEAddressDesc *target, short returnID, long transactionID, AppleEvent *result);
  8960. Creating and Duplicating Descriptor Records
  8961. pascal OSErr AECreateDesc    (DescType typeCode, const void* dataPtr, 
  8962. Size dataSize, AEDesc *result);
  8963. pascal OSErr AEDuplicateDesc
  8964. (const AEDesc *theAEDesc, AEDesc *result);
  8965. Creating Descriptor Lists and AE Records
  8966. pascal OSErr AECreateList    (const void* factoringPtr, Size factoredSize, Boolean isRecord, AEDescList *resultList);
  8967. Adding Items to Descriptor Lists
  8968. pascal OSErr AEPutPtr    (const AEDescList *theAEDescList, long index, 
  8969. DescType typeCode, const void* dataPtr, 
  8970. Size dataSize);
  8971. pascal OSErr AEPutDesc    (const AEDescList *theAEDescList, long index, const AEDesc *theAEDesc);
  8972. pascal OSErr AEPutArray    (const AEDescList *theAEDescList, 
  8973. AEArrayType arrayType, 
  8974. const AEArrayDataPointer *arrayPtr, 
  8975. DescType itemType, Size itemSize, 
  8976. long itemCount);
  8977. Adding Data and Descriptor Records to AE Records
  8978. pascal OSErr AEPutKeyPtr    (const AERecord *theAERecord, 
  8979. AEKeyword theAEKeyword, DescType typeCode, const void* dataPtr, Size dataSize);
  8980. pascal OSErr AEPutKeyDesc    (const AERecord *theAERecord, 
  8981. AEKeyword theAEKeyword, 
  8982. const AEDesc *theAEDesc);
  8983. Adding Parameters and Attributes to Apple Events
  8984. pascal OSErr AEPutParamPtr    (const AppleEvent *theAppleEvent, 
  8985. AEKeyword theAEKeyword, DescType typeCode, const void* dataPtr, Size dataSize);
  8986. pascal OSErr AEPutParamDesc    (const AppleEvent *theAppleEvent, 
  8987. AEKeyword theAEKeyword, 
  8988. const AEDesc *theAEDesc);
  8989. pascal OSErr AEPutAttributePtr
  8990. (const AppleEvent *theAppleEvent, 
  8991. AEKeyword theAEKeyword, DescType typeCode, const void* dataPtr, Size dataSize);
  8992. pascal OSErr AEPutAttributeDesc
  8993. (const AppleEvent *theAppleEvent, 
  8994. AEKeyword theAEKeyword, 
  8995. const AEDesc *theAEDesc);
  8996. Sending Apple Events
  8997. pascal OSErr AESend    (const AppleEvent *theAppleEvent, 
  8998. AppleEvent *reply, AESendMode sendMode, AESendPriority sendPriority, 
  8999. long timeOutInTicks, IdleProcPtr idleProc, 
  9000. EventFilterProcPtr filterProc);
  9001. Application-Defined Routines
  9002.  
  9003. pascal Boolean MyIdleFunction
  9004. (const EventRecord *event,
  9005. long *sleepTime, RgnHandle *mouseRgn);
  9006. pascal Boolean MyReplyFilter
  9007. (const EventRecord *event, 
  9008. long returnID, long transactionID,
  9009. AEAddressDesc sender);
  9010. Assembly-Language Summary
  9011.  
  9012. Trap Macros
  9013.  
  9014. Trap Macros Requiring Routine Selectors
  9015. _Pack8
  9016. Selector    Routine    
  9017. $0405    AEDuplicateDesc    
  9018. $0609    AEPutDesc    
  9019. $0610    AEPutKeyDesc    
  9020. $0610    AEPutParamDesc    
  9021. $0627    AEPutAttributeDesc    
  9022. $0706    AECreateList    
  9023. $0825    AECreateDesc    
  9024. $0A08    AEPutPtr    
  9025. $0A0F    AEPutKeyPtr    
  9026. $0A0F    AEPutParamPtr    
  9027. $0A16    AEPutAttributePtr    
  9028. $0B0D    AEPutArray    
  9029. $0B14    AECreateAppleEvent    
  9030. $0D17    AESend    
  9031.  
  9032. Result CodesnoErr    0    No error    
  9033. paramErr    –50    Parameter error (for example, value of handler pointer is NIL or odd)    
  9034. eLenErr    –92    Buffer too big to send    
  9035. memFullErr    –108    Not enough room in heap zone    
  9036. userCanceledErr    –128    User canceled an operation    
  9037. procNotFound    –600    No eligible process with specified process serial number    
  9038. bufferIsSmall    –607    Buffer is too small    
  9039. noOutstandingHLE    –608    No outstanding high-level event    
  9040. connectionInvalid    –609    Nonexistent signature or session ID    
  9041. noUserInteractionAllowed    –610    Background application sends event requiring authentication    
  9042. noPortErr    –903    Client hasn’t set 'SIZE' resource to indicate awareness of high-level events    
  9043. destPortErr    –906    Server hasn’t set 'SIZE' resource to indicate awareness of high-level events, or else is not present    
  9044. sessClosedErr    –917    The kAEDontReconnect flag in the sendMode parameter was set, and the server quit and then restarted    
  9045. errAECoercionFail    –1700    Data could not be coerced to the requested descriptor type    
  9046. errAEDescNotFound    –1701    Descriptor record was not found    
  9047. errAECorruptData    –1702    Data in an Apple event could not be read    
  9048. errAEWrongDataType    –1703    Wrong descriptor type    
  9049. errAENotAEDesc    –1704    Not a valid descriptor record    
  9050. errAEBadListItem    –1705    Operation involving a list item failed    
  9051. errAENewerVersion    –1706    Need a newer version of the Apple Event Manager    
  9052. errAENotAppleEvent    –1707    Event is not an Apple event    
  9053. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event handler    
  9054. errAEReplyNotValid    –1709    AEResetTimer was passed an invalid reply    
  9055. errAEUnknownSendMode    –1710    Invalid sending mode was passed    
  9056. errAEWaitCanceled    –1711    User canceled out of wait loop for reply or receipt    
  9057. errAETimeout    –1712    Apple event timed out    
  9058. errAENoUserInteraction    –1713    No user interaction allowed    
  9059. errAENotASpecialFunction    –1714    The keyword is not valid for a special function    
  9060. errAEParamMissed    –1715    Handler cannot understand a parameter the client considers required    
  9061. errAEUnknownAddressType    –1716    Unknown Apple event address type    
  9062. errAEHandlerNotFound    –1717    No handler found for an Apple event or a coercion, or no object callback function found    
  9063. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  9064. errAEIllegalIndex    –1719    Not a valid list index    
  9065. errAEImpossibleRange    –1720    The range is not valid because it is impossible for a range to include the first and last objects that were specified; an example is a range in which the offset of the first object is greater than the offset of the last object    
  9066. errAEWrongNumberArgs    –1721    The number of operands provided for the kAENot logical operator is not 1    
  9067. errAEAccessorNotFound    –1723    There is no object accessor function for the specified object class and token descriptor type    
  9068. errAENoSuchLogical    –1725    The logical operator in a logical descriptor record is not kAEAnd, kAEOr, or kAENot    
  9069. errAEBadTestKey    –1726    The descriptor record in a test key is neither a comparison descriptor record nor a logical descriptor record    
  9070. errAENotAnObjectSpec    –1727    The objSpecifier parameter of AEResolve is not an object specifier record    
  9071. errAENoSuchObject    –1728     A run-time resolution error, for example: object specifier record asked for the third element, but there are only two    
  9072. errAENegativeCount    –1729     Object-counting function returned negative value    
  9073. errAEEmptyListContainer    –1730    The container for an Apple event object is specified by an empty list    
  9074. errAEUnknownObjectType    –1731    Descriptor type of token returned by AEResolve is not known to server application     
  9075. errAERecordingIsAlreadyOn    –1732    Attempt to turn recording on when it is already on    
  9076.  
  9077.  
  9078.  
  9079. Listing 6-0
  9080. Table 6-0
  9081. Resolving and Creating Object Specifier Records
  9082. Contents
  9083. Resolving Object Specifier Records6-4
  9084. Descriptor Records Used in Object Specifier Records6-8
  9085. Object Class6-9
  9086. Container6-9
  9087. Key Form6-11
  9088. Key Data6-12
  9089. Key Data for a Property ID6-13
  9090. Key Data for an Object’s Name6-14
  9091. Key Data for a Unique ID6-14
  9092. Key Data for Absolute Position6-14
  9093. Key Data for Relative Position6-15
  9094. Key Data for a Test6-15
  9095. Key Data for a Range6-20
  9096. Installing Entries in the Object Accessor Dispatch Tables6-21
  9097. Installing Object Accessor Functions That Find Apple Event Objects6-23
  9098. Installing Object Accessor Functions That Find Properties6-27
  9099. Writing Object Accessor Functions6-28
  9100. Writing Object Accessor Functions That Find Apple Event Objects6-29
  9101. Writing Object Accessor Functions That Find Properties6-37
  9102. Defining Tokens6-39
  9103. Handling Whose Tests6-41
  9104. Writing Object Callback Functions6-45
  9105. Writing an Object-Counting Function6-48
  9106. Writing an Object-Comparison Function6-50
  9107. Writing Marking Callback Functions6-53
  9108. Creating Object Specifier Records6-55
  9109. Creating a Simple Object Specifier Record6-57
  9110. Specifying the Container Hierarchy6-61
  9111. Specifying a Property6-63
  9112. Specifying a Relative Position6-64
  9113. Creating a Complex Object Specifier Record6-64
  9114. Specifying a Test6-64
  9115. Specifying a Range6-72
  9116. Reference to Resolving and Creating Object Specifier Records6-75
  9117. Data Structures Used in Object Specifier Records6-75
  9118. Routines for Resolving and Creating Object Specifier Records6-77
  9119. Initializing the Object Support Library6-77
  9120. Setting Object Accessor Functions and Object Callback Functions6-77
  9121. Getting, Calling, and Removing Object Accessor Functions6-81
  9122. Resolving Object Specifier Records6-85
  9123. Deallocating Memory for Tokens6-87
  9124. Creating Object Specifier Records6-88
  9125. Application-Defined Routines6-94
  9126. Object Accessor Functions6-94
  9127. Object Callback Functions6-96
  9128. Summary of Resolving and Creating Object Specifier Records6-104
  9129. Pascal Summary6-104
  9130. Constants6-104
  9131. Data Types6-106
  9132. Routines for Resolving and Creating Object Specifier Records6-106
  9133. Application-Defined Routines6-108
  9134. C Summary6-109
  9135. Constants6-109
  9136. Data Types6-111
  9137. Routines for Resolving and Creating Object Specifier Records6-112
  9138. Application-Defined Routines6-114
  9139. Assembly-Language Summary6-115
  9140. Trap Macros6-115
  9141. Result Codes6-115
  9142. Resolving and Creating Object Specifier Records
  9143. This chapter describes how your application can use the Apple Event Manager and application-defined functions to resolve object specifier records. Your application must be able to resolve object specifier records to respond to core and functional-area Apple events defined in the Apple Event Registry: Standard Suites. 
  9144. For example, after receiving a Get Data event that requests a table in a document, your application can use the Apple Event Manager and application-defined functions to parse the object specifier record in the direct parameter, locate the requested table, and send a reply Apple event containing the table’s data back to the application that requested it.
  9145. This chapter also describes how your application can use the Apple Event Manager to create object specifier records. If you want to factor your application for Apple event recording, or if you want to send Apple events directly to other applications, you need to know how to create object specifier records.
  9146. To use this chapter, you should be familiar with the chapters “Introduction to Apple Events” and “Responding to Apple Events” in this book. The section “Working With Object Specifier Records,” which begins on page 3-32, provides a general introduction to the subject.
  9147. If you plan to create object specifier records, you should also be familiar with the chapter “Creating and Sending Apple Events.” If you are factoring your application, you should read the chapter “Recording Apple Events” before you write code for resolving or creating object specifier records.
  9148. This chapter begins with an overview of the way your application works with the Apple Event Manager to resolve object specifier records. It then describes
  9149. n    how the data in an object specifier record is organized
  9150. n    how to install entries in the object accessor tables
  9151. n    how to write object accessor and object callback functions
  9152. n    how to create an object specifier record
  9153. IMPORTANT
  9154. Versions 1.0 and 1.01 of the Apple Event Manager do not include the routines for resolving and creating object specifier records described in this chapter. To use these routines with those versions of the Apple Event Manager, you must link the Object Support Library (OSL) with your application when you build it, and call the AEObjectInit function before calling any of the routines.s  
  9155.  
  9156.  
  9157. Resolving Object Specifier Records
  9158.  
  9159. If an Apple event parameter consists of an object specifier record, your handler for the Apple event should resolve the object specifier record: that is, locate the Apple event objects it describes. The first step is to call the AEResolve function with the object specifier record as a parameter. 
  9160. The AEResolve function performs tasks that are required to resolve any object specifier record, such as parsing its contents, keeping track of the results of tests, and handling memory management. When necessary, AEResolve calls application-defined functions to perform tasks that are unique to the application, such as locating a specific Apple event object in the application’s data structures or counting the number of Apple event objects in a container.
  9161. Note
  9162. Object specifier records are only valid while the Apple event that contains them is being handled. For example, if an application receives an Apple event asking it to cut row 5 of a table, what was row 6 then becomes row 5, and the original object specifier record that referred to row 5 no longer refers to the same row.u
  9163. The AEResolve function can call two kinds of application-defined functions. Object accessor functions locate Apple event objects. Object callback functions perform other tasks that only an application can perform, such as counting, comparing, or marking Apple event objects. This section provides an overview of the way AEResolve calls object accessor and object callback functions when it resolves object specifier records. 
  9164. Each time AEResolve calls one of your application’s object accessor functions successfully, the object accessor function should return a special descriptor record created by your application, called a token, that identifies either an element in a specified container or a property of a specified Apple event object. The Apple Event Manager examines the token’s descriptor type but does nothing with the token’s data. When it needs to refer to the object the token identifies, the Apple Event Manager simply passes the token back to your application. 
  9165. Each object accessor function provided by your application should either find elements of a given object class in a container identified by a token of a given descriptor type, or find properties of an Apple event object identified by a token of a specified descriptor type. The Apple Event Manager uses the object class ID and the descriptor type of the token that identifies the object’s container to determine which object accessor function to call.
  9166. It is up to you to decide how many object accessor functions you need to write for your application. You can write one object accessor function that locates Apple event objects of several different object classes, or you can write separate object accessor functions for certain object classes. Similarly, you may want to use only one descriptor type for all the tokens returned by your object accessor functions, or you may want to use several descriptor types. The way you define your tokens depends on the needs of your application. 
  9167. You can use the AEInstallObjectAccessor function to create an object accessor dispatch table that the Apple Event Manager uses to map requests for Apple event objects to the appropriate object accessor function in your application. The Apple Event Manager uses the object class of each requested object and the descriptor type of the token that identifies the object’s container to determine which object accessor function to call. Depending on the container hierarchy for a given object specifier record and the way your application defines its object accessor functions, the Apple Event Manager may need to call a series of object accessor functions to resolve the nested object specifier records that describe an Apple event object’s container. For information about creating and using the object accessor dispatch table, see “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 6-21. 
  9168. Figure 6-1 illustrates the major steps involved in resolving an object specifier record. The SurfWriter application shown in Figure 6-1 receives a Get Data event whose direct parameter is an object specifier record for a table named “Summary of Sales” in a document named “Sales Report.” The SurfWriter application’s handler for the Get Data event calls the AEResolve function with the object specifier record as a parameter. The AEResolve function begins to parse the object specifier record. The first object accessor function that AEResolve calls is usually the function that can identify the Apple event object in the application’s default container—the outermost container in the container hierarchy. In Figure 6-1, the object specifier record for the document “Sales Report” specifies the default container, so the Apple Event Manager calls the object accessor function in the SurfWriter application that can locate a document in a container identified by a descriptor record of descriptor type typeNull. 
  9169. Figure 6-1    Resolving an object specifier record for a table in a document
  9170.  
  9171. After locating the document named “Sales Report,” the SurfWriter application returns a token to the Apple Event Manager—that is, a descriptor record that SurfWriter uses to identify the document. The Apple Event Manager examines the descriptor type of the token but does not need to know anything about the token’s data to continue parsing the object specifier record. Next, the Apple Event Manager calls the object accessor function that can identify a table in a container identified by a token of descriptor type typeMyDocToken. When the Apple Event Manager calls this object accessor function, it uses the token that describes the document to identify the table’s container. After the SurfWriter application has located the table named “Summary of Sales” in the document named “Sales Report,” it returns a token describing that table to the Apple Event Manager. 
  9172. After your application has successfully located an Apple event object, the Apple Event Manager disposes of all previous tokens returned during resolution of the object specifier record for the object. The Apple Event Manager disposes of tokens by calling either the AEDisposeDesc function or your application’s token disposal function, if you have provided one, which is an object callback function that disposes of a token. In Figure 6-1, the AEResolve function calls the SurfWriter application’s token disposal function to dispose of the token for the document after AEResolve receives the token for the table. After the SurfWriter application has disposed of the token for the document, the AEResolve function returns the result of the resolution—that is, the token for the requested table—to the handler in the SurfWriter application that originally called AEResolve. 
  9173. The Apple Event Manager can complete the cycle of parsing the object specifier record and calling the appropriate object accessor function to obtain a token as many times as necessary to identify every container in the container hierarchy and finish resolving an object specifier record, including disposing of the tokens for the containers. However, one token will always be left over—the token that identifies the requested Apple event object. After AEResolve returns this final token and your application performs the action requested by the Apple event, it is up to your application to dispose of the token. Your application can do so by calling the AEDisposeToken function, which in turn calls either AEDisposeDesc or your application’s token disposal function. 
  9174. You need to provide a token disposal function only if a call to AEDisposeDesc is not sufficient by itself to dispose of a token or if you provide marking callback functions, which are three object callback functions that allow your application to use its own marking scheme rather than tokens when identifying large groups of Apple event objects. Your application is not required to provide marking callback functions. 
  9175. To handle object specifier records that specify a test, your application must provide two object callback functions: (a) an object-counting function, which counts the number of elements of a given object class in a given container so that the Apple Event Manager can determine how many elements it must test to find the element or elements that meet a specified condition, and (b) an object-comparison function, which compares one element to another element or to a descriptor record and returns TRUE or FALSE. 
  9176. Your application may also provide an error callback function that can identify which descriptor record caused the resolution of an object specifier record to fail. Your application is not required to provide an error callback function.
  9177. If your application resolves object specifier records without the help of the Apple Event Manager, it must extract the equivalent descriptor records and coerce them as necessary to get access to their data. The Apple Event Manager includes coercion handlers for these coercions; for information about this default coercion handling, see Table 4-1 on page 4-43.
  9178. For more information about object accessor functions, see “Writing Object Accessor Functions,” which begins on page 6-28. For more information about object callback functions, see “Writing Object Callback Functions,” which begins on page 6-45.  
  9179. The next section, “Descriptor Records Used in Object Specifier Records,” describes how the data in an object specifier record is interpreted by the Apple Event Manager.  
  9180.  
  9181. Descriptor Records Used in Object Specifier Records
  9182.  
  9183. An object specifier record is a coerced AE record of descriptor type typeObjectSpecifier. The data to which its data handle refers consists of four keyword-specified descriptor records:
  9184. Keyword    Value    Description of data    
  9185. keyAEDesiredClass    'want'    A four-character code for the object class    
  9186. keyAEContainer    'from'    An object specifier record (or in some cases a descriptor record with a handle whose value is NIL) that identifies the container for the requested objects    
  9187. keyAEKeyForm    'form'    A four-character code for the key form    
  9188. keyAEKeyData    'seld'    Data or nested descriptor records that specify a property, name, position, range, or test, depending on the key form    
  9189.  
  9190. This section describes the descriptor types and data associated with each of these keywords. You need this information if your application resolves or creates object specifier records.
  9191. For a summary of the descriptor types and key forms discussed in this section, see 
  9192. Table 6-11 on page 6-76. For an overview of object specifier records, see “Working With Object Specifier Records,” which begins on page 3-32.
  9193. Object Class
  9194.  
  9195. The object class of the requested objects is identified by an object class ID. The corresponding keyword-specified descriptor record takes this form: 
  9196. Keyword    Descriptor type    Data    
  9197. keyAEDesiredClass    typeType    Object class ID    
  9198.  
  9199. The Apple Event Registry: Standard Suites defines constants for the standard object class IDs.
  9200. Container
  9201.  
  9202. The container for the requested objects is usually the object in which they are located. It can be identified in one of four ways:
  9203. Keyword    Descriptor type    Data    
  9204. keyAEContainer    typeObjectSpecifier    Object specifier record.    
  9205.     typeNull    Value of data handle is NIL. Specifies the default container at the top of the container hierarchy.    
  9206.     typeObjectBeingExamined    Value of data handle is NIL. Specifies the container for elements that are tested one at a time; used only within key data for key form formTest.    
  9207.     typeCurrentContainer    Value of data handle is NIL. Specifies a container for an element that demarcates one boundary in a range. Used only within key data for key form formRange.    
  9208.  
  9209. The data that describes a container usually consists of another object specifier record. The ability to nest one object specifier record within another in this way makes it possible to identify a chain of containers that fully describes the location of one or more Apple event objects.
  9210. For example, Figure 6-2 shows nested object specifier records that specify the first row of a table named “Summary of Sales” in a document named “Sales Report.” The container specified by the object specifier record at the bottom of the figure describes the outermost container in the container hierarchy—the container for the document “Sales Report.”  
  9211. Because a container must be specified for each Apple event object in a container hierarchy, a null descriptor record (that is, a descriptor record whose descriptor type is typeNull and whose data handle has the value NIL) is used to specify the application’s default container—the outermost container for any container hierarchy in that application.    
  9212. Figure 6-2    Nested object specifier records that specify a container hierarchy
  9213.  
  9214. Note
  9215. The format used in Figure 6-2 and similar figures throughout this chapter does not show the structure of the nested object specifier records as they exist within an Apple event. Instead, these figures show what you would obtain after calling AEGetKeyDesc repeatedly to extract the object specifier records from an Apple event record.
  9216. When you call AEGetKeyDesc to extract a null descriptor record, the function returns a descriptor record of type AEDesc with a descriptor type of typeNull and a data handle whose value is 0.u
  9217. The object specifier data at the bottom of Figure 6-2 uses a null descriptor record to specify the document’s container—that is, the default container for the application. The object specifier record for the document identifies the document named “Sales Report”; the object specifier record for the table identifies the table named “Summary of Sales” in the document “Sales Report”; and the object specifier record for the row identifies the first row of the table named “Summary of Sales” in the document “Sales Report.”
  9218. An object specifier record in an Apple event parameter almost always includes nested object specifier records that specify the container hierarchy for the requested Apple event object. For the nested object specifier records shown in Figure 6-2, the relationship between each Apple event object and its container is always simple containment: it is located inside its container. 
  9219. In other cases, the specified container may not actually contain the requested Apple event object. Instead, the relationship between a “container” and a specified object can be defined differently, depending on the key form. For example, the key form formRelativePosition indicates that the requested object is before or after its container. 
  9220. Object specifier records that specify the key form formTest or formRange require key data that consists of several nested descriptor records, including additional object specifier records that identify either a group of elements to be tested or the boundary elements that demarcate a range. These object specifier records use two special descriptor types to specify containers: typeObjectBeingExamined (see page 6-19), which specifies a container that changes as a group of elements are tested one at a time, and typeCurrentContainer (see page 6-20), which specifies the container for a boundary element in a range. Both of these descriptor types require a data handle whose value is NIL, since they act much like variables whose value is supplied by the Apple Event Manager according to other information provided in the container hierarchy. 
  9221. Key Form
  9222.  
  9223. The key form indicates how the key data should be interpreted. It can be specified by one of eight constants: 
  9224. Keyword    Descriptor type    Data    
  9225. keyAEKeyForm    typeEnumerated    formPropertyID
  9226. formName
  9227. formUniqueID
  9228. formAbsolutePosition
  9229. formRelativePosition
  9230. formTest
  9231. formWhose
  9232. formRange    
  9233.  
  9234. The next section describes the key data that corresponds to each key form.
  9235. Key Data
  9236.  
  9237. The nature of the information provided by the key data depends both on the specified key form and on the descriptor type of the descriptor record for the key data. Table 6-1 summarizes these relationships for the standard key forms. 
  9238. Table 6-1    Standard descriptor types used with keyAEKeyData(continued)
  9239. Key form    Descriptor type    Data    
  9240. formPropertyID     typeType    Property ID for an element’s property     
  9241. formName    typeChar or other text type    Element’s name    
  9242. formUniqueID    Any appropriate type    A value that uniquely identifies an object within its container or across an application     
  9243. formAbsolutePosition    typeLongInteger    Offset from beginning (positive) or end (negative) of container    
  9244.     typeAbsoluteOrdinal    kAEFirst
  9245. kAEMiddle
  9246. kAELast
  9247. kAEAny
  9248. kAEAll    
  9249. formRelativePosition    typeEnumerated    kAENext
  9250. kAEPrevious    
  9251. formTest    typeCompDescriptor    (see Table 6-2 on page 6-16)     
  9252.     typeLogicalDescriptor    (see Table 6-3 on page 6-17)    
  9253. formRange    typeRangeDescriptor    (see Table 6-4 on page 6-20)     
  9254. formWhose    typeWhoseDescriptor    (see Table 6-5 on page 6-42)     
  9255.  
  9256. Most applications that resolve object specifier records need to support only the key forms formPropertyID, formName, formUniqueID, formAbsolutePosition, formRelativePosition, and formRange explicitly. You do not need to support these key forms for all object classes; for example, words usually do not have names, so most applications should return errAEEventNotHandled if they receive a request for a word by name. 
  9257. If your application provides an object-counting function and an object-comparison function in addition to the appropriate object accessor functions, the Apple Event Manager can handle formTest automatically.
  9258. The Apple Event Manager uses the key form formWhose internally to optimize resolution of object specifier records that specify formTest. Applications that translate tests into their own query languages need to support formWhose explicitly. “Handling Whose Tests,” which begins on page 6-41, describes formWhose in detail.
  9259. You can define custom key forms and the format for corresponding data for use by your own application if necessary. If you think you need to do this, check with the Apple Event Registrar first to find out whether existing key forms or others still under development can be adapted to the needs of your application. 
  9260. One simple kind of key form involves identifying an object on the basis of a specified property. For example, the corresponding data for key form formUniqueID (defined in the Apple Event Registry: Standard Suites) always consists of a unique ID for the requested object. This ID is stored as a property identified by the constant pID. The four-character code that corresponds to both formUniqueID and pID is 'ID  '. 
  9261. If you discover that you do need to define a custom key form based on a property, use the same four-character code for both the key form and the associated property. 
  9262. The rest of this section describes how the key data for the other key forms shown in Table 6-1 identifies Apple event objects.
  9263. Key Data for a Property ID
  9264.  
  9265. The key data for formPropertyID is specified by a descriptor record of descriptor type typeType. The Apple Event Registry: Standard Suites defines constants for the standard property IDs.
  9266. An object specifier record for a property specifies cProperty as the object class ID, an object specifier record for the object that contains the property as the container, formPropertyID as the key form, and a constant such as pFont as the key data. For example, if you were sending a Set Data event to change the font of a word to Palatino®, you could specify the data for the object specifier record in the direct parameter as follows:
  9267. Keyword    Descriptor type    Data    
  9268. keyAEDesiredClass    typeType    cProperty    
  9269. keyAEContainer    typeObjectSpecifier    Object specifier record for word to which property belongs    
  9270. keyAEKeyForm    typeEnumerated    formPropertyID    
  9271. keyAEKeyData    typeType    pFont    
  9272.  
  9273. In this example, the Set Data Apple event parameter identified by the keyword keyAETheData would specify Palatino as the value to which to set the specified property. The reply Apple event for a subsequent Get Data event that included an object specifier record for the same property would return Palatino in the parameter identified by the keyword keyAEResult.   
  9274. Key Data for an Object’s Name
  9275.  
  9276. The key data for formName is specified by a descriptor record whose data consists of text, with a descriptor type such as typeChar or typeIntlText. 
  9277. Figure 6-2 on page 6-10 includes two object specifier records that specify formName.
  9278. Key Data for a Unique ID
  9279.  
  9280. The key data for formUniqueID consists of a value that identifies an object. This ID must be unique either within the container, at a minimum, or unique across the application. A unique ID can be specified by a descriptor record of any appropriate type; for example, type typeInteger. 
  9281. Key Data for Absolute Position
  9282.  
  9283. The key data for formAbsolutePosition consists of an integer that specifies either an offset or an ordinal position. For descriptor type typeLongInteger, the data is either a positive integer, indicating the offset of the requested element from the beginning of the container, or a negative integer, indicating its offset from the end of the container. The first object specifier record shown in Figure 6-2 on page 6-10 specifies formAbsolutePosition with key data that consists of the positive integer 1.
  9284. For descriptor type typeAbsoluteOrdinal, the data consists of one of these constants: 
  9285. Constant    Meaning    
  9286. kAEFirst    The first element in the specified container     
  9287. kAEMiddle    The element in the middle of the specified container     
  9288. kAELast    The last element in the specified container     
  9289. kAEAny    A single element chosen at random from the specified container    
  9290. kAEAll    All the elements in the specified container     
  9291.  
  9292. If an object specifier record specifies kAEMiddle and the number of elements in the container is even, the Apple Event Manager rounds down; for example, the second word would be the “middle” word in a range of four words.
  9293. Key Data for Relative Position
  9294.  
  9295. The key data for formRelativePosition is specified by a descriptor record of type typeEnumerated whose data consists of one of these constants: 
  9296. Constant    Meaning    
  9297. kAENext    The Apple event object after the specified container     
  9298. kAEPrevious    The Apple event object before the specified container     
  9299.  
  9300. The “container” can be a single Apple event object or a group of Apple event objects; the requested elements are located immediately before or immediately after it, not inside it. 
  9301. If your application can locate objects of the same class by absolute position, it can easily locate the same objects by relative position. For example, all applications that support formAbsolutePosition can easily locate the table immediately after a container specified as another table named “Summary of Sales.” 
  9302. Some applications may also be able to locate an object of one class before or after an object of another class. For example, a word processor might be able to locate the paragraph immediately after a container specified as a table named “Summary of Sales.”
  9303. Key Data for a Test
  9304.  
  9305. The key data for formTest is specified by either a comparison descriptor record or a logical descriptor record. If your application provides an object-counting function and an object-comparison function in addition to the appropriate object accessor functions, the Apple Event Manager can handle formTest for you. Some applications may perform tests more efficiently by translating them into the application’s own query language. For information about handling tests yourself, see “Handling Whose Tests,” which begins on page 6-41.   
  9306. The container for objects that pass a test can be one or more Apple event objects. The objects specified are those in the container that pass the test specified by the key data. For example, an object specifier record can describe “the first row in which the First Name column equals ‘John’ and the Last Name column equals ‘Chapman’ in the table ‘MyAddresses’ of the database ‘SurfDB.’” To resolve such an object specifier record, the Apple Event Manager must evaluate a logical expression that applies the logical operator AND to two separate comparisons for each row: a comparison of the First Name column to the word “John” and a comparison of the Last Name column to the word “Chapman.” 
  9307. The Apple Event Manager evaluates comparisons and logical expressions on the basis of the information in comparison descriptor records and logical descriptor records. A comparison descriptor record is a coerced AE record of type typeCompDescriptor that specifies an Apple event object and either another Apple event object or data for the Apple Event Manager to compare to the first object. The Apple Event Manager can also use the information in a comparison descriptor record to compare elements in a container, one at a time, either to an Apple event object or to data. The data for a comparison descriptor record consists of three keyword-specified descriptor records with the descriptor types and data shown in Table 6-2.
  9308. Table 6-2    Keyword-specified descriptor records for typeCompDescriptor
  9309. Keyword    Descriptor type    Data    
  9310. keyAECompOperator    typeType    kAEGreaterThan 
  9311. kAEGreaterThanEquals
  9312. kAEEquals
  9313. kAELessThan
  9314. kAELessThanEquals
  9315. kAEBeginsWith
  9316. kAEEndsWith
  9317. kAEContains    
  9318. keyAEObject1    typeObjectSpecifier    Object specifier data     
  9319.     typeObjectBeingExamined    Value of data handle is NIL     
  9320. keyAEObject2    typeObjectSpecifier    Object specifier data for object to be compared     
  9321.     typeObjectBeingExamined    Value of data handle is NIL    
  9322.     any other type (AEDesc)    Data to be compared     
  9323.  
  9324. The keyword keyAEObject1 identifies a descriptor record for the element that is currently being compared to the object or data specified by the descriptor record for the keyword keyAEObject2. Either object can be described by a descriptor record of type typeObjectSpecifier or typeObjectBeingExamined. A descriptor record of typeObjectBeingExamined acts as a placeholder for each of the successive elements in a container when the Apple Event Manager tests those elements one at a time. The keyword keyAEObject2 can also be used with a descriptor record of any other descriptor type whose data is to be compared to each element in a container.
  9325. You don’t have to support all the available comparison operators for all Apple event objects; for example, the “begins with” operator probably doesn’t make sense for objects of type cRectangle. It is up to you to decide which comparison operators are appropriate for your application to support, and how to interpret them. 
  9326. If necessary, you can define your own custom comparison operators. If you think you need to do this, check with the Apple Event Registrar first to find out whether existing definitions of comparison operators or definitions still under development can be adapted to the needs of your application.
  9327. A logical descriptor record is a coerced AE record of type typeLogicalDescriptor that specifies a logical expression—that is, an expression that the Apple Event Manager evaluates to either TRUE or FALSE. The logical expression is constructed from a logical operator (one of the Boolean operators AND, OR, or NOT) and a list of logical terms to which the operator is applied. Each logical term in the list can be either another logical descriptor record or a comparison descriptor record. The Apple Event Manager short-circuits its evaluation of a logical expression as soon as one part of the expression fails a test. For example, if while testing a logical expression such as A AND B AND C the Apple Event Manager discovers that A AND B is not true, it will evaluate the expression to FALSE without testing C.
  9328. The data for a logical descriptor record consists of two keyword-specified descriptor records with the descriptor types and data shown in Table 6-3.
  9329. Table 6-3    Keyword-specified descriptor records for typeLogicalDescriptor
  9330. Keyword    Descriptor type    Data    
  9331. keyAELogicalOperator    typeEnumerated    kAEAND
  9332. kAEOR
  9333. kAENOT    
  9334. keyAELogicalTerms    typeAEList    One or more comparison or logical descriptor records    
  9335.  
  9336. If the logical operator is AND or OR, the list can contain any number of logical terms, and the logical operator is applied to all the terms in the list. For example, the logical descriptor data shown in Figure 6-4 on page 6-19 consists of the logical operator AND and a list of logical terms that contains two comparison descriptor records. The entire logical descriptor record corresponds to the logical expression “the First Name column equals ‘John’ AND the Last Name column equals ‘Chapman.’” If the logical operator is NOT, the list must contain a single term. 
  9337. Figure 6-3 shows four object specifier records that specify the container hierarchy for the first row in the table “MyAddresses” of the database “SurfDB” that meets a test. The object specifier record at the top of Figure 6-3 specifies the first row contained in the set of rows that form its container. The container for the first row is specified by an object specifier record for a set of rows that meet a test. The two object specifier records at the bottom of Figure 6-3 specify the table named “MyAddresses,” which contains the rows to be tested, in the database named “SurfDB.” 
  9338. Figure 6-3    The container hierarchy for the first row in a table that meets a test
  9339.  
  9340. The object specifier record in Figure 6-3 for a set of rows that meet a test specifies formTest. The corresponding key data consists of the logical descriptor record shown in Figure 6-4, which applies the logical operator AND to two logical terms: a comparison descriptor record that specifies all the rows in the container (the table “MyAddresses”) in which the column named “First Name” equals “John,” and another comparison descriptor record that specifies all the rows in which the column named “Last Name” equals “Chapman.” A row in the table “MyAddresses” passes the test only if both comparison descriptor records evaluate as TRUE.
  9341. Figure 6-4    A logical descriptor record that specifies a test
  9342.  
  9343. The keyword-specified descriptor records with the keyword keyAEObject1 in 
  9344. Figure 6-4 each consist of an object specifier record that identifies a column by name. The row for each column is specified by a descriptor record of typeObjectBeingExamined, which acts as a placeholder for each row as the Apple Event Manager tests successive rows in the table. The Apple event object specified by each of these object specifier records consists of a column in the row. The Apple Event Manager (with the help of an object-comparison function) compares the contents of the column in successive rows to the string identified by the keyword keyAEObject2 using the comparison operator identified by the keyword keyAECompOperator.  
  9345. Key Data for a Range
  9346.  
  9347. The key data for formRange is specified by a range descriptor record, which is a coerced AE record of type typeRangeDescriptor that identifies two Apple event objects marking the beginning and end of a range of elements. The data for a range descriptor record consists of two keyword-specified descriptor records with the descriptor types and data shown in Table 6-4. 
  9348. Table 6-4    Keyword-specified descriptor records in a descriptor record of type typeRangeDescriptor
  9349. Keyword    Descriptor type    Data    
  9350. keyAERangeStart    typeObjectSpecifier    An object specifier record for the first Apple event object in the desired range    
  9351. keyAERangeStop    typeObjectSpecifier    An object specifier record for the last Apple event object in the desired range    
  9352.  
  9353. The elements that identify the beginning and end of the range, which are known as boundary objects, do not have to belong to the same object class as the elements in the range itself. If the boundary objects belong to the same object class as the elements in the range, the boundary objects are included in the range. For example, the range of tables specified by boundary elements that are also tables would include the two boundary tables. 
  9354. The container for boundary objects is usually the same as the container for the entire range, in which case the container for a boundary object can be specified by a placeholder—that is, a descriptor record of type typeCurrentContainer whose data handle has the value NIL. 
  9355. When AEResolve calls an object accessor function to locate a range of objects, the Apple Event Manager replaces the descriptor record of type typeCurrentContainer with a token for the container of each boundary object. When using AEResolve to resolve the object specifier record, your application doesn’t need to examine the contents of this token, because the Apple Event Manager keeps track of it. If your application attempts to resolve some or all of the object specifier record without calling AEResolve, the application may need to examine the token before it can locate the boundary objects. The token provided by the Apple Event Manager for a boundary object’s container is a descriptor record of type typeToken whose data handle refers to a structure of type ccntTokenRecord.
  9356. TYPE ccntTokenRecord = 
  9357. RECORD
  9358.     tokenClass:                    DescType;                    {class ID of container }
  9359.                                             { represented by token}
  9360.     token:                    AEDesc;                    {token for current container}
  9361. END;
  9362. This data type is of interest only if you attempt to resolve an object specifier record for a range without calling AEResolve. Otherwise, the Apple Event Manager keeps track of the container.  
  9363.  
  9364. Installing Entries in the Object Accessor Dispatch Tables
  9365.  
  9366. If the direct parameter for an Apple event consists of an object specifier record, your handler for the event should call the AEResolve function to resolve the object specifier record: that is, to find the Apple event objects or properties it describes. The AEResolve function resolves the object specifier record with the help of object accessor functions provided by your application. Your application installs entries for its object accessor functions in an object accessor dispatch table, which is used by the Apple Event Manager to map requests for Apple event objects or their properties to the appropriate object accessor functions. 
  9367. After being called by AEResolve, an object accessor function should return a token that identifies (in whatever manner is appropriate for your application) the specified Apple event object or property. An object accessor function also returns a result code that indicates whether it found the Apple event object or property. The token, which is a descriptor record of data type AEDesc, can be of any descriptor type, including descriptor types you define yourself. For an overview of the way AEResolve works with your application’s object accessor functions to locate Apple event objects, see “Resolving Object Specifier Records,” which begins on page 6-4.
  9368. Each object accessor function provided by your application should either find elements of a specified object class contained in an Apple event object identified by a token of a specified descriptor type, or find properties of an Apple event object identified by a token of a specified descriptor type. To determine which object accessor function to dispatch, the Apple Event Manager uses the object class ID specified in an object specifier record and the descriptor type of the token that identifies the requested object’s container. For object accessor functions that find properties, you should specify the object class ID as the constant cProperty. 
  9369. To install entries in your application’s object accessor dispatch table, use the AEInstallObjectAccessor function. For each object class and property your application supports, you should install entries that specify
  9370. n    the object class of the requested Apple event object or property
  9371. n    the descriptor type of the token used to identify the container for the requested Apple event object or property
  9372. n    the address of the object accessor function that finds objects or properties of the specified object class in containers described by tokens of the specified descriptor type
  9373. n    a reference constant
  9374. You provide this information in the first four parameters to the AEInstallObjectAccessor function. The fifth parameter allows you to indicate whether the entry should be added to your application’s object accessor dispatch table or the system object accessor dispatch table.
  9375. The system object accessor dispatch table is a table in the system heap that contains object accessor functions available to all processes running on the same computer. The object accessor functions in your application’s object accessor dispatch table are available only to your application. If AEResolve cannot find an object accessor function for the Apple event object class in your application’s object accessor dispatch table, it looks in the system object accessor dispatch table. If it doesn’t find an object accessor function there either, it returns the result code errAEAccessorNotFound.  
  9376. If AEResolve successfully calls the appropriate object accessor function in either the application object accessor dispatch table or the system object accessor dispatch table, the object accessor function returns a token and result code. The AEResolve function uses the token and result code to continue resolving the object specifier record. If, however, the token identifies the final Apple event object or property in the container hierarchy, AEResolve returns the token for the final resolution in the theToken parameter.
  9377. If the AEResolve function calls an object accessor function in the system object accessor dispatch table, your Apple event handler may not recognize the descriptor type of the token returned by the function. If this happens, your handler should attempt to coerce the token to an appropriate descriptor type. If coercion fails, return the result code errAEUnknownObjectType. When your handler returns this result code, the Apple Event Manager attempts to locate a system Apple event handler that can recognize the token.
  9378. It is up to you to decide how many object accessor functions you need to write and install for your application. You can install one object accessor function that locates Apple event objects of several different object classes, or you can write separate object accessor functions for certain object classes. Similarly, you may want to use only one descriptor type for all the tokens returned by your object accessor functions, or you may want to use several descriptor types. The sections that follow provide examples of alternative approaches.
  9379. For more information about object accessor functions, see “Writing Object Accessor Functions,” which begins on page 6-28.
  9380. Installing Object Accessor Functions That Find Apple Event Objects
  9381.  
  9382. Listing 6-1 demonstrates how to add entries to your application’s object accessor dispatch table for the object class cText and three of its element classes: the object classes cWord, cItem, and cChar. In this example, the container for each of these object classes is identified by a token that consists of a descriptor record of descriptor type typeMyText. 
  9383. Listing 6-1    Installing object accessor functions that find elements of different classes for container tokens of the same type
  9384. myErr := AEInstallObjectAccessor(cText, typeMyText, 
  9385.                                             @MyFindTextObjectAccessor,
  9386.                                             0, FALSE);
  9387. IF myErr <> noErr THEN DoError(myErr);
  9388. myErr := AEInstallObjectAccessor(cWord, typeMyText, 
  9389.                                             @MyFindWordObjectAccessor,
  9390.                                             0, FALSE);
  9391. IF myErr <> noErr THEN DoError(myErr);
  9392. myErr := AEInstallObjectAccessor(cItem, typeMyText, 
  9393.                                             @MyFindItemObjectAccessor,
  9394.                                             0, FALSE);
  9395. IF myErr <> noErr THEN DoError(myErr);
  9396. myErr := AEInstallObjectAccessor(cChar, typeMyText, 
  9397.                                             @MyFindCharObjectAccessor,
  9398.                                             0, FALSE);
  9399. IF myErr <> noErr THEN DoError(myErr);    
  9400. The first call to AEInstallObjectAccessor in Listing 6-1 adds an entry to the application’s object accessor dispatch table. This entry indicates that the AEResolve function should call the MyFindTextObjectAccessor function when resolving any Apple event object with the cText object class and a container identified by a token of descriptor type typeMyText. The other calls to AEInstallObjectAccessor in Listing 6-1 add entries for Apple event objects of object classes cWord, cItem, and cChar in a container identified by a token of descriptor type typeMyText. For example, because all the entries created by the code in Listing 6-1 specify the descriptor type typeMyText for the token that identifies the container, the AEResolve function calls the MyFindWordObjectAccessor function to locate a requested word regardless of whether the container for the word is a run of text, another word, a paragraph, or an item. 
  9401. The fourth parameter for the AEInstallObjectAccessor function specifies a reference constant passed to your handler by the Apple Event Manager each time AEResolve calls your object accessor function. Your application can use this reference constant for any purpose. If your application doesn’t use the reference constant, you can use 0 as the value, as shown in Listing 6-1. 
  9402. The last parameter for the AEInstallObjectAccessor function is a Boolean value that determines whether the entry is added to the system object accessor dispatch table (TRUE) or to your application’s object accessor dispatch table (FALSE). 
  9403. If you add an object accessor function to the system object accessor dispatch table, the function that you specify must reside in the system heap. If there was already an entry in the system object accessor dispatch table for the same object class and container descriptor type, that entry is replaced unless you chain it to your system handler. You can do this the same way you chain a previously installed system Apple event handler to your own system handler. See the description of AEInstallEventHandler on page 4-62 for details.
  9404. sWARNING
  9405. Before an application calls a system object accessor function, system software has set up the A5 register for the calling application. For this reason, if you provide a system object accessor function, it should never use A5 global variables or anything that depends on a particular context; otherwise, the application that calls the system object accessor function may crash.s
  9406. The code shown in Listing 6-1 installs a separate object accessor function for each object class, even though the code specifies the same descriptor type for tokens that identify the containers for Apple event objects of each class. Most word-processing applications can specify the same object accessor function as well as the same token descriptor type for Apple event objects of these four classes, in which case the code shown in Listing 6-1 can be altered as shown in Listing 6-2.
  9407. Listing 6-2    Installing one object accessor function that finds elements of different classes for container tokens of one type
  9408. myErr := AEInstallObjectAccessor(cText, typeMyText, 
  9409.                                             @MyFindTextObjectAccessor,
  9410.                                             0, FALSE);
  9411. IF myErr <> noErr THEN DoError(myErr);
  9412. myErr := AEInstallObjectAccessor(cWord, typeMyText, 
  9413.                                             @MyFindTextObjectAccessor,
  9414.                                             0, FALSE);
  9415. IF myErr <> noErr THEN DoError(myErr);
  9416. myErr := AEInstallObjectAccessor(cItem, typeMyText, 
  9417.                                             @MyFindTextObjectAccessor,
  9418.                                             0, FALSE);
  9419. IF myErr <> noErr THEN DoError(myErr);
  9420. myErr := AEInstallObjectAccessor(cChar, typeMyText, 
  9421.                                             @MyFindTextObjectAccessor,
  9422.                                             0, FALSE);
  9423. IF myErr <> noErr THEN DoError(myErr);
  9424. In some situations you may want to write different object accessor functions to locate Apple event objects of the same object class in containers identified by tokens of different descriptor types. For example, the code in Listing 6-3 installs two different object accessor functions: one that finds a word in a container identified by a token of type typeMyTextToken, and one that finds a word in a container identified by a token of typeMyGraphicTextToken.
  9425. Listing 6-3    Installing object accessor functions that find elements of the same class for container tokens of different types
  9426. myErr := AEInstallObjectAccessor(cWord, typeMyTextToken, 
  9427.                                             @MyFindTextObjectAccessor,
  9428.                                             0, FALSE);
  9429. IF myErr <> noErr THEN DoError(myErr);
  9430. myErr := AEInstallObjectAccessor(cWord, typeMyGraphicTextToken, 
  9431.                                             @MyFindGrphcTextObjectAccessor,
  9432.                                             0, FALSE);
  9433. IF myErr <> noErr THEN DoError(myErr);
  9434. Every application must provide one or more object accessor functions that can find Apple event objects in the default container, which is always identified by a token of descriptor type typeNull. Listing 6-4 demonstrates how to add entries to your application’s object accessor dispatch table for the object classes cWindow and cDocument. The container for each of these classes is identified by a token of descriptor type typeNull, which specifies an application’s default container.
  9435. Listing 6-4    Installing object accessor functions that locate elements of different classes in the default container
  9436. myErr := AEInstallObjectAccessor(cWindow, typeNull, 
  9437.                                             @MyFindWindowObjectAccessor,
  9438.                                             0, FALSE);
  9439. IF myErr <> noErr THEN DoError(myErr);
  9440. myErr := AEInstallObjectAccessor(cDocument, typeNull, 
  9441.                                             @MyFindDocumentObjectAccessor,
  9442.                                             0, FALSE);
  9443. IF myErr <> noErr THEN DoError(myErr);
  9444. For any entry in your object accessor dispatch table, you can specify a wildcard value for the object class, for the descriptor type of the token used to identify the container, or for both. You specify a wildcard by supplying the typeWildCard constant when installing an entry into the object accessor dispatch table. A wildcard value matches all possible values.   
  9445. If an object accessor dispatch table contains one entry for a specific object class and a specific token descriptor type, and another entry that is identical except that it specifies a wildcard value for either the object class or the token descriptor type, the Apple Event Manager dispatches the more specific entry. For example, if an object accessor dispatch table includes one entry that specifies the object class as cWord and the token descriptor type as typeMyTextToken, and another entry that specifies the object class as cWord and the token descriptor type as typeWildCard, the Apple Event Manager dispatches the object accessor function associated with the entry that specifies typeMyTextToken.
  9446. If you specify typeWildCard as the first parameter and typeMyToken as the second parameter for the AEInstallObjectAccessor function and no other entry in the dispatch table matches more exactly, the Apple Event Manager calls the object accessor function that you specify in the third parameter when resolving Apple event objects of any object class in containers identified by tokens of the typeMyToken descriptor type.
  9447. If you specify cText as the first parameter and typeWildCard as the second parameter for the AEInstallObjectAccessor function and no other entry in the dispatch table matches more exactly, the Apple Event Manager calls the object accessor function that you specify in the third parameter when resolving Apple event objects of the object class cText in containers identified by tokens of any descriptor type. 
  9448. If you specify typeWildCard for both the first and second parameters of the AEInstallObjectAccessor function and no other entry in the dispatch table matches more exactly, the Apple Event Manager calls the object accessor function that you specify in the third parameter when resolving Apple event objects of any object class in containers identified by tokens of any descriptor type. 
  9449. Once the Apple Event Manager finds a matching entry, whether exact or involving type typeWildCard, that is the only object accessor function it calls for that object class and token descriptor type. If that function fails, the Apple Event Manager won’t look for another matching entry in the same table.
  9450. Installing Object Accessor Functions That Find Properties
  9451.  
  9452. The Apple event object to which a property belongs is that property’s container. You should add entries to your application’s object accessor dispatch table that specify object accessor functions for finding properties in containers identified by tokens of various descriptor types. Object specifier records do not specify a property’s specific object class; instead, they specify the constant cProperty as the class ID for any property. Similarly, you should specify the constant cProperty as the object class for an object accessor function that can find any property of a container identified by a token of a given descriptor type. If you need to install different object accessor routines for finding properties of Apple event objects that belong to different object classes, you must use different descriptor types for the tokens that represent those Apple event objects. 
  9453. For example, to specify an object accessor function that locates properties of Apple event objects identified by tokens of descriptor type typeMyToken, you can add a single entry to the object accessor dispatch table:
  9454. myErr := AEInstallObjectAccessor(cProperty, typeMyToken,
  9455.                                             @MyFindPropertyObjectAccessor,
  9456.                                             0, FALSE);
  9457. IF myErr <> noErr THEN DoError(myErr);
  9458. The code in this example adds an object accessor function to the application’s object accessor dispatch table that can find any property of any container identified by a token of descriptor type typeMyToken. If the second parameter were specified as typeWildCard, the MyFindPropertyObjectAccessor function would have to be capable of finding any property of any Apple event object in your application except for those found by handlers with more specific entries in the object accessor dispatch table. 
  9459.  
  9460.  
  9461. Writing Object Accessor Functions
  9462.  
  9463. If the direct parameter for an Apple event consists of an object specifier record, your handler for the event should call the AEResolve function to resolve the object specifier record: that is, to find the Apple event objects or properties it describe. The AEResolve function resolves object specifier records with the help of object accessor functions provided by your application. For an overview of the way AEResolve works with your application’s object accessor functions to locate Apple event objects, see “Resolving Object Specifier Records,” which begins on page 6-4. 
  9464. This section describes how to write object accessor functions. You need to read this section if your application supports the Core suite or any of the functional-area suites in the Apple Event Registry: Standard Suites.
  9465. Your application should provide object accessor functions that can find Apple event objects and their properties for all object classes supported by your application, including their corresponding properties and element classes. Because the Apple Event Manager dispatches object accessor functions according to the class ID of the requested Apple event object and the descriptor type of the token that identifies its container, you have a great deal of flexibility in deciding what object accessor functions you need to write for your application. The installation and dispatching of object accessor functions are described in “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 6-21.
  9466. For example, if your application is a word processor, one object accessor function will probably work equally well for Apple event objects of object classes cParagraph, cItem, and cWord located in containers identified by tokens of descriptor type myTextToken. If you use a single descriptor type for tokens that identify any containers in which objects of these three object classes can be found, you can dispatch requests for all such elements to the same object accessor function. However, the same word processor might use one descriptor type for tokens identifying containers of class cCell and another descriptor type for tokens identifying containers of class cColumn—in which case it would need an object accessor function for each descriptor type.
  9467. For each object class that your application supports, your application should also provide one object accessor function that can find all the properties of that object class, or one object accessor function that can find all the properties of several object classes.
  9468. Here’s the declaration for a sample object accessor function:
  9469. FUNCTION MyObjectAccessor (desiredClass: DescType; 
  9470.                                     containerToken: AEDesc; 
  9471.                                     containerClass: DescType;
  9472.                                     keyForm: DescType; keyData: AEDesc;
  9473.                                     VAR theToken: AEDesc; 
  9474.                                     theRefCon: LongInt): OSErr;
  9475. The AEResolve function passes the following information to your object accessor function: the object class ID of the requested Apple event objects, the object class of their container, a token that identifies the specific container in which to look for them, the key form and key data that specify how to locate them, and the reference constant associated with the object accessor function. Your object accessor function uses this information to locate the requested objects. 
  9476. Most applications that resolve object specifier records need to support only the key forms formPropertyID, formName, formUniqueID, formAbsolutePosition, formRelativePosition, and formRange explicitly. You do not need to support these key forms for all object classes; for example, words usually do not have names, so most applications should return errAEEventNotHandled if they receive a request for a word by name. 
  9477. If your application provides an object-counting function and an object-comparison function in addition to the appropriate object accessor functions, the Apple Event Manager can handle formTest automatically.
  9478. The Apple Event Manager uses the key form formWhose internally to optimize resolution of object specifier records that specify formTest. Only applications that translate tests into their own query languages need to support formWhose explicitly. “Handling Whose Tests,” which begins on page 6-41, describes formWhose in detail.
  9479. If your object accessor function successfully locates the requested Apple event objects, your application should return the noErr result code and a token that identifies them. The token can be of any descriptor type, as long as it is a descriptor record. For example, to identify a file, your application might use a descriptor record of descriptor type typeAlias or typeFSS. To identify an open document, your application might define its own descriptor type, such as typeMyDocToken, for a descriptor record whose data handle refers to a pointer to a document record. For more information about tokens, see “Defining Tokens” on page 6-39. 
  9480. IMPORTANT
  9481. Object accessor functions must not have side effects that change the number or order of elements in a container while an object specifier record is being resolved. If the number of elements in a container is changed during the resolution of an object specifier record, the Apple Event Manager may not be able to locate all the elements.s
  9482. Writing Object Accessor Functions That Find Apple Event Objects
  9483.  
  9484. The first three listings in this section demonstrate how to write three object accessor functions that might be called in the following situation: An application receives a Get Data event with a direct parameter that consists of an object specifier record for the first word in the third paragraph of a document. The application’s handler for the Get Data event calls the AEResolve function to resolve the object specifier record. The AEResolve function first calls the application’s object accessor function for objects of class cDocument in containers identified by a token of descriptor type typeNull. 
  9485. The AEResolve function passes these values to the MyFindDocumentObjectAccessor function shown in Listing 6-5: in the desiredClass parameter, the constant cDocument; in the containerToken parameter, a descriptor record of descriptor type typeNull with a data handle whose value is NIL; in the containerClass parameter, the constant typeNull; in the keyForm parameter, the constant formName; in the keyData parameter, a descriptor record of descriptor type typeText whose data consists of the string "MyDoc"; and the reference constant specified in the application’s object accessor dispatch table.
  9486. Listing 6-5    An object accessor function that locates Apple event objects of object class cDocument
  9487. FUNCTION MyFindDocumentObjectAccessor 
  9488.                                         (desiredClass: DescType; 
  9489.                                          containerToken: AEDesc; 
  9490.                                          containerClass: DescType;
  9491.                                          keyForm: DescType; keyData: AEDesc;
  9492.                                          VAR token: AEDesc; 
  9493.                                          theRefCon: LongInt): OSErr;
  9494. VAR
  9495.     docName:                        Str255;
  9496.     actSize:                        Size;
  9497.     foundDoc:                        Boolean;
  9498.     foundDocRecPtr:                        MyDocumentRecordPtr;
  9499. BEGIN
  9500.     IF keyform = formName THEN
  9501.     BEGIN
  9502.         {get the name of the document from the key data}
  9503.         MyGetStringFromDesc(keyData, docName, actSize);
  9504.         {look for a document with the given name by }
  9505.         { searching all document records}
  9506.         MySearchDocRecs(docName, foundDocRecPtr, foundDoc);
  9507.         IF NOT foundDoc THEN
  9508.             MyFindDocumentObjectAccessor := kObjectNotFound
  9509.         ELSE     {create token that identifies the document}
  9510.             MyFindDocumentObjectAccessor := 
  9511.                     AECreateDesc(typeMyDocToken, @foundDocRecPtr,
  9512.                                         SizeOf(foundDocRecPtr), token);
  9513.     END
  9514.     {handle the other key forms you support}
  9515.     ELSE
  9516.         MyFindDocumentObjectAccessor := kKeyFormNotSupported;
  9517. END;
  9518. The MyFindDocumentObjectAccessor function uses the information in the keyForm and keyData parameters to find the specified document. If it finds the Apple event object, MyFindDocumentObjectAccessor returns a token of descriptor type typeMyDocToken to AEResolve. The data handle for this token refers to a pointer to a document record (see Figure 6-5 on page 6-39). The MyFindDocumentObjectAccessor function returns this token and the noErr result code to the AEResolve function.
  9519. In the Get Data example, the token returned to AEResolve by the MyFindDocumentObjectAccessor function identifies the document “MyDoc.” The AEResolve function then calls the application’s object accessor function for objects of class cParagraph in containers identified by a token of descriptor type typeMyDocToken. 
  9520. In this case, AEResolve passes these values to the MyFindParaObjectAccessor function shown in Listing 6-6: in the desiredClass parameter, the constant cParagraph; in the containerToken parameter, the token returned by the MyFindDocumentObjectAccessor function; in the containerClass parameter, the constant cDocument; in the keyForm parameter, the constant formAbsolutePosition; in the keyData parameter, a descriptor record with the typeLongInteger descriptor type and data that consists of the value 3 (indicating the third paragraph); and the reference constant specified in the application’s object accessor dispatch table.
  9521. Listing 6-6    An object accessor function that locates Apple event objects of object class cParagraph
  9522. FUNCTION MyFindParaObjectAccessor (desiredClass: DescType; 
  9523.                                                 containerToken:     AEDesc; 
  9524.                                                 containerClass: DescType;
  9525.                                                 keyForm: DescType; 
  9526.                                                 keyData: AEDesc; 
  9527.                                                 VAR token: AEDesc; 
  9528.                                                 theRefCon: LongInt): OSErr;
  9529. VAR
  9530.     index:                        LongInt;
  9531.     {MyFoundTextRecord is an application-defined data type } 
  9532.     { consisting of three fields: start, ending, and docPtr} 
  9533.     foundParaRec:                        MyFoundTextRecord;
  9534.     foundParaStart:                        LongInt;
  9535.     foundParaEnd:                        LongInt;
  9536.     foundDocRecPtr:                        MyDocumentRecordPtr;
  9537.     success:                        Boolean;
  9538. BEGIN
  9539.     IF keyForm = formAbsolutePosition THEN
  9540.     BEGIN
  9541.         {get the index of the paragraph from the key data}
  9542.         MyGetIndexFromDesc(keyData, index);
  9543.         {get the desired paragraph by index}
  9544.         success := MyGetPara(index, containerToken, foundParaStart, 
  9545.                                     foundParaEnd, foundDocRecPtr);
  9546.         IF NOT success THEN
  9547.             MyFindParaObjectAccessor := kObjectNotFound
  9548.         ELSE     {create token that identifies the paragraph}
  9549.         BEGIN
  9550.             foundParaRec.start := foundParaStart;
  9551.             foundParaRec.ending := foundParaEnd;
  9552.             foundParaRec.docPtr := foundDocRecPtr;
  9553.             MyFindParaObjectAccessor := 
  9554.                     AECreateDesc(typeMyTextToken, @foundParaRec,
  9555.                                         SizeOf(foundParaRec), token);
  9556.         END;
  9557.     END
  9558.         {handle the other key forms you support}
  9559.     ELSE 
  9560.         MyFindParaObjectAccessor := kKeyFormNotSupported;
  9561. END;
  9562. The MyFindParaObjectAccessor function uses another application-defined function, MyGetPara, to search the data structures associated with the document and find the desired paragraph. If it finds the paragraph, MyGetPara returns a value that identifies the beginning of the paragraph, a value that identifies the end of the paragraph, and a pointer to the document (which MyGetPara gets from the containerToken parameter). The MyFindParaObjectAccessor function returns an application-defined token that contains this information. This token is of descriptor type typeMyTextToken; it describes a range of characters that can be used to identify any range of text, including a paragraph or a word. The MyFindParaObjectAccessor function returns this token and the noErr result code to the AEResolve function. 
  9563. In the Get Data example, the token returned to AEResolve by the MyFindParaObjectAccessor function identifies the third paragraph in the document “MyDoc.” The AEResolve function then calls the application’s object accessor function for objects of class cWord in containers identified by a token of descriptor type typeMyTextToken. 
  9564. In this case, the AEResolve function passes these values to the MyFindWordObjectAccessor function shown in Listing 6-7: in the desiredClass parameter, the constant cWord; in the containerToken parameter, the token returned by the MyFindParaObjectAccessor function (a token of descriptor type typeMyTextToken that identifies a paragraph); in the containerClass parameter, the constant cParagraph; in the keyForm parameter, the constant formAbsolutePosition; in the keyData parameter, a descriptor record with the typeLongInteger descriptor type and data that consists of the value 1 (indicating the first word); and the reference constant specified in the application’s object accessor dispatch table.
  9565. The MyFindWordObjectAccessor function uses another application-defined function, MyGetWord, to search the paragraph to find the desired word. If it finds the word, MyGetWord returns a value that identifies the beginning of the word, a value that identifies the end of the word, and a pointer to the document (which MyGetWord gets from the containerToken parameter). The MyFindWordObjectAccessor function returns a token that contains this information. This token is also of descriptor type typeMyTextToken; in this case, the token identifies a specific word. The MyFindWordObjectAccessor function returns this token and the noErr result code to the AEResolve function, which in turn returns the token to the Get Data event handler that originally called AEResolve. 
  9566. Listing 6-7    An object accessor function that locates Apple event objects of object class cWord
  9567.  
  9568. FUNCTION MyFindWordObjectAccessor 
  9569.                                         (desiredClass: DescType; 
  9570.                                          containerToken: AEDesc; 
  9571.                                          containerClass: DescType;
  9572.                                          keyForm: DescType; keyData: AEDesc;
  9573.                                          VAR token: AEDesc; 
  9574.                                          theRefCon: LongInt): OSErr;
  9575. VAR
  9576.     index:                        LongInt;
  9577.     foundWordRec:                        MyFoundTextRecord;
  9578.     foundWordStart:                        LongInt;
  9579.     foundWordEnd:                        LongInt;
  9580.     foundDocRecPtr:                        MyDocumentRecPtr;
  9581.     success:                        Boolean;
  9582. BEGIN
  9583.     IF keyForm = formAbsolutePosition THEN
  9584.     BEGIN
  9585.         {get the index of the word from the key data}
  9586.         MyGetIndexFromDesc(keyData, index);
  9587.         {get the desired word by index}
  9588.         success := MyGetWord(index, containerToken, foundWordStart, 
  9589.                                     foundWordEnd, foundDocRecPtr);
  9590.         IF NOT success THEN
  9591.             MyFindWordObjectAccessor := kObjectNotFound
  9592.         ELSE     {create token that identifies the paragraph}
  9593.         BEGIN
  9594.             foundWordRec.start := foundWordStart;
  9595.             foundWordRec.ending := foundWordEnd;
  9596.             foundWordRec.docPtr := foundDocRecPtr;
  9597.             MyFindWordObjectAccessor := 
  9598.                     AECreateDesc(typeMyTextToken, @foundWordRec,
  9599.                                         SizeOf(foundWordRec), token);
  9600.         END;
  9601.     END
  9602.     {handle the other key forms you support}
  9603.     ELSE 
  9604.         MyFindWordObjectAccessor := kKeyFormNotSupported;
  9605. END;
  9606. Listing 6-5 on page 6-30 shows an object accessor function that locates a document in the default container. Every application must provide one or more object accessor functions that can find Apple event objects in the default container, which is always identified by a descriptor record of descriptor type typeNull. Listing 6-8 provides another example of an object accessor function that locates an Apple event object in the default container. If the MyFindWindowObjectAccessor function shown in Listing 6-8 were installed in an application’s object accessor dispatch table, the AEResolve function would call it as necessary to locate an object of class cWindow in a container identified by a token of descriptor type typeNull.
  9607. Listing 6-8    An object accessor function that locates Apple event objects of object class cWindow
  9608. FUNCTION MyFindWindowObjectAccessor (desiredClass: DescType; 
  9609.                                                  containerToken: AEDesc; 
  9610.                                                  containerClass: DescType;
  9611.                                                  keyForm: DescType; 
  9612.                                                  keyData: AEDesc;
  9613.                                                  VAR token: AEDesc; 
  9614.                                                  theRefCon: LongInt): OSErr;
  9615. VAR
  9616.     windowName:                    Str255;
  9617.     actSize:                    Size;
  9618.     windTitle:                    Str255;
  9619.     window:                    WindowPtr;
  9620.     index, iLoop:                    Integer;
  9621.     found:                    Boolean;
  9622. BEGIN
  9623.     IF keyForm = formName THEN
  9624.     BEGIN
  9625.         {get the name of the window to find from the keyData }
  9626.         { parameter. MyGetStringFromDesc gets data out of an }
  9627.         { AEDesc and returns a string and the string's size}
  9628.         MyGetStringFromDesc(keyData, windowName, actSize);
  9629.         {look for a window with the given name}
  9630.         window := FrontWindow;
  9631.         found := FALSE;
  9632.         WHILE ((window <> NIL) AND (found = FALSE)) DO 
  9633.         BEGIN
  9634.             GetWTitle(window, windTitle);
  9635.             found := EqualString(windTitle, windowName, FALSE, TRUE); 
  9636.             IF NOT found THEN
  9637.                 window := WindowPtr(WindowPeek(window)^.nextWindow);
  9638.         END;             {of while}
  9639.     END {of formName}
  9640.     ELSE
  9641.     IF keyForm = formAbsolutePosition THEN
  9642.         {find the window given an index in key data}    
  9643.         BEGIN            {get the index from the key data}                    
  9644.             MyGetIndexFromDesc(keyData, index);
  9645.             found := FALSE;
  9646.             iLoop := 0;
  9647.             window := FrontWindow;
  9648.             WHILE (window <> NIL) AND (found <> TRUE) DO
  9649.             BEGIN
  9650.                 iLoop := iLoop +1;
  9651.                 IF iLoop = index THEN
  9652.                     found := TRUE
  9653.                 ELSE
  9654.                 window := WindowPtr(WindowPeek(window)^.nextWindow);
  9655.             END; {of while}
  9656.         END     {of formAbsolutePosition}
  9657.     {handle the other key forms you support}
  9658.     ELSE
  9659.     BEGIN
  9660.         MyFindWindowObjectAccessor := kKeyFormNotSupported;
  9661.         Exit(MyFindWindowObjectAccessor);
  9662.     END;
  9663.     IF window = NIL THEN
  9664.         MyFindWindowObjectAccessor := kObjectNotFound
  9665.     ELSE     {create token that identifies the window}
  9666.         MyFindWindowObjectAccessor := 
  9667.                     AECreateDesc(typeMyWindow, @window, 
  9668.                                         SizeOf(window), token);
  9669. END;
  9670. The keyForm parameter of the MyFindWindowObjectAccessor function describes how the function should interpret the keyData parameter. If the key form is formName, then the key data contains the name of the window to locate. If the key form is formAbsolutePosition, the key data contains the position of the window to locate in the window list; for example, a value of 1 identifies the frontmost window.
  9671. The MyFindWindowObjectAccessor function supports only the formName and formAbsolutePosition key forms. Your object accessor functions should support all key forms that make sense for the kinds of objects the functions can locate.
  9672. For the formName keyword, the MyFindWindowObjectAccessor function starts with the frontmost window and compares the window’s title to the name specified by the keyData parameter. It continues this search until it reaches either the end of the window list or finds a match. If the MyFindWindowObjectAccessor function finds a match, it uses the AECreateDesc function to create a descriptor record for the token, specifying the application-defined typeMyWindow descriptor type and the data for this descriptor type as a window pointer. 
  9673. The MyFindWindowObjectAccessor function then sets its function result appropriately, and the AEResolve function either returns this function result and token, or uses the returned token to request the next Apple event object in the container hierarchy, such as a document in the window. 
  9674. Writing Object Accessor Functions That Find Properties
  9675.  
  9676. The Apple event object to which a property belongs is that property’s container. Your application should provide an object accessor function for finding properties in containers identified by tokens of various descriptor types. Your application does not need to be given a property’s specific object class in order to find that property; instead, you can specify the object class ID for any property with the constant cProperty. Thus, you can write a single object accessor function that can find any property of an object identified by a token of a given descriptor type. 
  9677. To install such an object accessor function, you can add a single entry to the object accessor dispatch table that specifies the desired object class as cProperty for a given token descriptor type. For example, Listing 6-9 shows an object accessor function that identifies any property of a window.
  9678. Listing 6-9    An object accessor function that identifies any property of a window
  9679.  
  9680. FUNCTION MyFindPropertyOfWindowObjectAccessor 
  9681.                                         (desiredClass: DescType; 
  9682.                                         containerToken:     AEDesc; 
  9683.                                         containerClass: DescType;
  9684.                                         keyForm: DescType; keyData: AEDesc;
  9685.                                         VAR token: AEDesc; 
  9686.                                         theRefCon: LongInt): OSErr;
  9687. VAR
  9688.     theProperty: DescType;
  9689. BEGIN
  9690.     MyFindPropertyOfWindowObjectAccessor := noErr;
  9691.     MyGetPropFromKeyData(keyData, theProperty);
  9692.     IF keyForm = formPropertyID THEN
  9693.     BEGIN
  9694.         IF theProperty = pName THEN
  9695.             {create token that identifies name property of the }
  9696.             { window}
  9697.             MyCreateToken(typeMyWindowProp, containerToken, pName, 
  9698.                                 token)
  9699.         ELSE
  9700.         IF theProperty = pBounds THEN
  9701.             {create token that identifies bounds property of the }
  9702.             { window}
  9703.             MyCreateToken(typeMyWindowProp, containerToken, pBounds, 
  9704.                                 token)
  9705.  
  9706.         {create tokens for other properties as appropriate}
  9707.  
  9708.         ELSE
  9709.             MyFindPropertyOfWindowObjectAccessor := 
  9710.                                                         kErrorPropNotFound;
  9711.     END
  9712.     ELSE
  9713.         MyFindPropertyOfWindowObjectAccessor := 
  9714.                                                         kKeyFormNotSupported;
  9715. END; 
  9716. The MyFindPropertyOfWindowObjectAccessor function takes a token that identifies a window and creates a token that identifies the requested property of that window. See Figure 6-6 on page 6-40 for an illustration of the logical organization of a token of descriptor type typeMyWindowProp.
  9717. This simplified example merely translates information about the requested property and the window to which it belongs into the form of a token of type typeMyWindowProp. This token can then be used by Apple event handlers to identify the corresponding window and its property, so that a handler can either retrieve the value of the property (for example, a Get Data handler) or change the value of the property (for example, a Set Data handler). Like other tokens, a token that identifies a property should always contain a reference to the corresponding property and the object to which it belongs—not a copy of the data for that object’s property. 
  9718. Defining Tokens
  9719.  
  9720. It is up to you to decide how many token descriptor types you need to define for your application. In many cases you may be able to define one token that can identify Apple event objects of several different object classes, such as a token of type typeMyTextToken that identifies Apple event objects of object classes cText, cWord, cItem, and cChar. In other cases you may need to define specific token descriptor types for specific object classes.
  9721. For example, the MyFindDocumentObjectAccessor routine shown in Listing 6-5 on page 6-30 returns a token of descriptor type typeMyDocToken, which identifies a document record.
  9722. CONST                                             {application-defined token}
  9723.     typeMyDocToken                            = 'docr';             {identifies a document record}
  9724. Figure 6-5 shows the logical arrangement of a descriptor record of descriptor type typeMyDocToken whose data is specified by a pointer to a document record.
  9725. Figure 6-5    Descriptor record for an application-defined token that identifies a document
  9726.  
  9727. The MyFindPropertyOfWindowObjectAccessor routine shown in Listing 6-9 returns a token of descriptor type typeMyWindowProp for every property that it can locate.
  9728. CONST                                             {application-defined token}
  9729.     typeMyWindowProp                            = 'wprp';             {a window pointer and a }
  9730.                                              { property ID}
  9731. Figure 6-6 shows the logical arrangement of a descriptor record of descriptor type typeMyWindowProp that identifies the bounds property of a window. Its data consists of a window pointer and the constant pBounds. The application can use this token either to return or to change the window’s bounds setting, depending on the Apple event that specified the property. If the token specified pName instead, the application could use it either to return the window’s name as a string or to change the window’s name.
  9732. Figure 6-6    Descriptor record for an application-defined token that identifies the pbounds property of a window
  9733.  
  9734. A token’s data should always contain a reference to the corresponding Apple event objects—not a copy of the data for those objects. This allows the same token to be used for both reading and writing tokens.
  9735. It’s often possible to use the same token type for objects of several object classes, or for both an object of a given class and one of its properties. A token’s data is private to your application and can be organized in any way that is convenient.
  9736. When an object accessor function that supports key form formRange locates a range of Apple event objects, it should normally return a descriptor list (AEDescList) of tokens for the individual objects. A typical exception is an object accessor function that returns a range of objects of class cText, which should return a single token representing the entire range. For example, an object accessor function that finds “all the characters from char 1 to char 1024” should return a token that consists of a list of 1024 objects, each of class cChar, whereas an object specifier function that finds “all the text from char 1 to char 1024” should return a single token for a single item of class cText that is 1024 characters long. 
  9737. A token is valid only until the Apple Event Manager has located the requested element in the container the token represents and returned another token for the element. The Apple Event Manager disposes of intermediate tokens after it finishes resolving an object specifier record, but one token is always left over—the token that identifies the specified Apple event object or objects. Your application should dispose of this final token by calling the AEDisposeToken function, which in turn calls your application’s token disposal function (if one exists), an optional object callback function that disposes of a token. See page 6-99 for the declaration of a token disposal function. 
  9738. If your application does not provide a token disposal function, the Apple Event Manager uses the AEDisposeDesc function to dispose of tokens. This function does the job as long as disposing of tokens involves nothing more than simply disposing of a descriptor record. Otherwise, you need to provide a custom token disposal function. For example, suppose the data field of a token descriptor record contains a handle to a block that in turn contains references to memory for the Apple event object referred to by the token. In this case, the application should provide a token disposal function that performs the tasks required to dispose of the token and any associated structures.  
  9739. Handling Whose Tests
  9740.  
  9741. If your application provides an object-counting function and an object-comparison function in addition to the appropriate object accessor functions, the Apple Event Manager can resolve object specifier records that specify formTest without any other assistance from your application. The Apple Event Manager translates object specifier records of key form formTest into object specifier records of key form formWhose. This involves collapsing the key form and key data from two object specifier records in a container hierarchy into one object specifier record with the key form formWhose. 
  9742. Some applications may find it more efficient to translate whose tests into their own query languages rather than letting the Apple Event Manager handle the tests. This is useful only for applications that can make use of a test combined with either an absolute position or a range to locate objects. If you want the Apple Event Manager to let your application handle whose tests, set the kAEIDoWhose flag in the callbackFlags parameter of the AEResolve function. If for any reason one of your application’s object accessor functions chooses not to handle a particular whose descriptor record, it should return errAEEventNotHandled as the result code, and the Apple Event Manager will try again using the original object specifier records, just as if the kAEIDoWhose flag were not set.
  9743. The key data for formWhose is specified by a whose descriptor record, which is a coerced AE record of descriptor type typeWhoseDescriptor. The data for a whose descriptor record consists of the two keyword-specified descriptor records shown in Table 6-5.   
  9744. Table 6-5    Keyword-specified descriptor records for typeWhoseDescriptor
  9745. Keyword    Descriptor type    Data    
  9746. keyAEIndex    typeLongInteger     Offset of requested element in group of elements that pass a test      
  9747.     typeAbsoluteOrdinal    kAEFirst
  9748. kAEMiddle
  9749. kAELast
  9750. kAEAny
  9751. kAEAll    
  9752.     typeWhoseRange    Whose range descriptor record    
  9753. keyAETest    typeCompDescriptor    Comparison descriptor record     
  9754.     typeLogicalDescriptor    Logical descriptor record    
  9755.  
  9756. A whose descriptor record is never created directly by an application. The Apple Event Manager creates a whose descriptor record whenever an object specifier record of key form formTest is used to describe the container for elements described by an object specifier record of key form formAbsolutePosition or formRange, with some exceptions as noted in this section. 
  9757. For example, Figure 6-3 on page 6-18 shows four object specifier records that show the container hierarchy for the first row that meets a test in the table “MyAddresses” of the database “SurfDB.” The top two object specifier records in that figure use the key forms formAbsolutePosition and formTest to describe elements in a container. When it receives these two object specifier records, the Apple Event Manager collapses them into one, as shown in Figure 6-7. It then calls the application’s object-counting function to find out how many objects of class cRow the table contains and the object-comparison function to test the rows in the table until it finds the first row that passes the test. 
  9758. Figure 6-7    A container hierarchy created by the Apple Event Manager using a whose descriptor record
  9759.  
  9760. If the elements to be tested are described by an object specifier record of key form formAbsolutePosition or formRange but are not of the same object class as their container, the Apple Event Manager cannot collapse the existing object specifier records into a whose descriptor record. Instead, the Apple Event Manager creates a whose descriptor record as if a third object specifier record of key form formAbsolutePosition and kAEAll were inserted between the object specifier record for the container and that for the tested elements. For example, the Apple Event Manager would interpret a request for “character 1 of word whose first letter = ‘a’” as “character 1 of every word whose first letter = ‘a’”.
  9761. When an object specifier record of key form formTest is used to describe the container for elements described by an object specifier record of key form formRange, the Apple Event Manager will, under certain conditions, coerce the corresponding range descriptor record to a whose range descriptor record, which is a coerced AE record of typeWhoseRange. The data for a whose range descriptor record consists of two keyword-specified descriptor records with the descriptor types and data shown in 
  9762. Table 6-6. 
  9763. Table 6-6    Keyword-specified descriptor records for typeWhoseRange
  9764. Keyword    Descriptor type    Data    
  9765. keyAEWhoseRangeStart    typeLongInteger     Offset of beginning of range    
  9766.     typeAbsoluteOrdinal    kAEFirst
  9767. kAEMiddle
  9768. kAELast
  9769. kAEAny
  9770. kAEAll    
  9771. keyAEWhoseRangeStop    typeLongInteger     Offset of end of range    
  9772.     typeAbsoluteOrdinal    kAEFirst
  9773. kAEMiddle
  9774. kAELast
  9775. kAEAny
  9776. kAEAll     
  9777.  
  9778. A whose range descriptor record describes the absolute position of the boundary elements, within the set of all elements that pass a test, that identify the beginning and end of the desired range.
  9779. The Apple Event Manager coerces a range descriptor record to a whose range descriptor record if the specified container and its elements are of the same class, if the container for the specified range of elements is a group of Apple event objects that pass a test, and if the boundary objects in the original range descriptor record meet these conditions: 
  9780. n    Both boundary objects are of the same object class as the Apple event objects in the range they specify.
  9781. n    The object specifier record for each boundary object specifies its container with a descriptor record of descriptor type typeCurrentContainer.
  9782. n    The object specifier record for each boundary object specifies a key form of formAbsolutePosition. 
  9783. If these conditions are not met, the Apple Event Manager doesn’t create a whose range descriptor record. Instead, as described earlier in this section, the Apple Event Manager creates a whose descriptor record as if the original request specified every element that passed the test.
  9784. If your application sets the kAEIDoWhose flag in the callbackFlags parameter of AEResolve, you should provide object accessor functions that can handle formWhose. These functions should coerce the whose descriptor record specified as key data for an object specifier record to an AE record and extract the data from the AE record by calling the AEGetKeyPtr and AEGetKeyDesc functions. If the keyword-specified descriptor record with the keyword keyAEIndex specifies descriptor type typeWhoseRange, your object accessor function must also coerce that descriptor record to an AE record and extract the data. Your object accessor function should then attempt to locate the requested objects and, if successful, return a token that identifies them.
  9785. If your application sets the kAEIDoWhose flag and attempts to resolve every whose descriptor record it receives, the Apple Event Manager does not attempt to resolve object specifier records of any key form. The object-counting and object-comparison functions are never called, and your application is solely responsible for determining the formats and types of all tokens.  
  9786.  
  9787. Writing Object Callback Functions
  9788.  
  9789. If an Apple event parameter consists of an object specifier record, your handler for the Apple event typically calls AEResolve to begin the process of locating the requested Apple event object or objects. In turn, AEResolve calls object accessor functions and, if necessary, object callback functions provided by your application.
  9790. Every application that supports Apple event objects should provide object accessor functions that can locate Apple event objects belonging to any of the supported object classes. For an overview of the way AEResolve calls object accessor functions to locate Apple event objects described by object specifier records, see “Resolving Object Specifier Records,” which begins on page 6-4.
  9791. In addition to object accessor functions, your application can provide up to seven object callback functions:
  9792. n    An object-counting function counts the number of elements of a specified class in a specified container, so that the Apple Event Manager can determine how many elements it must examine to find the element or elements that pass a test. Your application must provide one object-counting function to handle object specifier records that specify tests. (See “Writing an Object-Counting Function,” which begins on page 6-48.)
  9793. n    An object-comparison function compares one element either to another element or to a descriptor record and returns either TRUE or FALSE. Your application must provide one object-comparison function to handle object specifier records that specify tests. (See “Writing an Object-Comparison Function” on page 6-50.)
  9794. n    A token disposal function disposes of a token after your application calls the AEDisposeToken function. If your application doesn’t provide a token disposal function, the Apple Event Manager uses the AEDisposeDesc function instead. Your application must provide a token disposal function if it requires more than a call to AEDisposeDesc to dispose of one of its tokens. This is true, for example, if your application supports marking by modifying its own data structures. (See page 6-99 for the declaration of a token disposal function.)
  9795. n    An error callback function gives the Apple Event Manager an address to which to write the descriptor record it is currently working with if an error occurs while AEResolve is attempting to resolve an object specifier record. Your application is not required to provide an error callback function. (See page 6-100 for the declaration of an error callback function.)
  9796. n    Three marking callback functions are used by the Apple Event Manager to get a mark token from your application, to mark specific Apple event objects, and to pare down a group of marked Apple event objects. Your application must provide all three marking functions if it supports marking. (See “Writing Marking Callback Functions” on page 6-53.)
  9797. To make your object callback functions available to the Apple Event Manager, use the AESetObjectCallbacks function: 
  9798. myErr := AESetObjectCallbacks (@MyCompareObjects,
  9799.                                          @MyCountObjects, @MyDisposeToken,
  9800.                                          @MyGetMarkToken, @MyMark, 
  9801.                                          @MyAdjustMarks, @MyGetErrDesc);
  9802. Each parameter to the AESetObjectCallbacks function consists of either a pointer to the corresponding application-defined function or NIL if no function is provided. The AESetObjectCallbacks function sets object callback functions that are available only to your application. To set system object callback functions, which are available to all applications and processes running on the same computer, use the AEInstallSpecialHandler function as described on page 4-100.
  9803. To handle object specifier records that specify tests, your application must provide an object-counting function and an object-comparison function. The Apple Event Manager calls your application’s object-counting function to determine the number of Apple event objects in a specified container that need to be tested. The Apple Event Manager calls your application’s object-comparison function when it needs to compare one Apple event object to either another Apple event object or to a value in a descriptor record.
  9804. If your application does not provide a token disposal function, the Apple Event Manager uses the AEDisposeDesc function to dispose of tokens. This function does the job as long as disposing of tokens involves nothing more than simply disposing of a descriptor record. Otherwise, you need to provide custom token disposal function. For example, suppose the data field of a token descriptor record contains a handle to a block that in turn contains references to storage for the Apple event object referred to by the token. In this case, the application can provide a token disposal function that performs the tasks required to dispose of the token and any associated structures.  
  9805. Whenever more than one Apple event object passes a test, AEResolve can either return a list of tokens or make use of a target application’s ability to mark its own objects. Sometimes a list of tokens can become unmanageably large. For example, if a Get Data event asks for the names and addresses of all customers with a specified zip code who have purchased a specified product, the object accessor function that locates all the customers with the specified zip code might return a list of many thousands of tokens; the elements identified by those tokens would then have to be tested for the specified product. However, if your application uses some method of marking objects, you can choose simply to mark the requested objects rather than returning a list of tokens. “Writing Marking Callback Functions” on page 6-53 describes how to do this. If your application supports marking by modifying its own data structures, you must provide a token disposal function. 
  9806. When one of your application’s Apple event handlers calls the AEResolve function, the handler should pass a value in the callbackFlags parameter that specifies whether your application supports whose descriptor records or provides marking callback functions. You can add the following constants, as appropriate, to provide a value for the callbackFlags parameter: 
  9807. CONST kAEIDoMinimum                            =    $0000; {does not handle whose tests or }
  9808.                                             { provide marking callbacks}
  9809.         kAEIDoWhose                    =    $0001; {supports key form formWhose}
  9810.         kAEIDoMarking                    =    $0004; {provides marking functions}
  9811. For example, this code instructs the Apple Event Manager to call any marking functions previously set with the AESetObjectCallbacks function while resolving the object specifier record in the objectSpecifier parameter:
  9812. VAR
  9813.     objectSpecifier:    AEDesc;
  9814.     resultToken:        AEDesc;
  9815.     myErr:              OSErr;
  9816.  
  9817. myErr := AEResolve(objectSpecifier, kAEIDoMarking, resultToken); 
  9818. If any of the marking callback functions are not installed, AEResolve returns the error errAEHandlerNotFound.
  9819. IMPORTANT
  9820. If your application doesn’t specify kAEIDoWhose, the Apple Event Manager attempts to resolve all object specifier records of key form formTest. To do so, the Apple Event Manager uses your application’s object-counting and object-comparison functions, and returns a token of type typeAEList.
  9821. If your application does specify kAEIDoWhose, the Apple Event Manager does not attempt to resolve object specifier records of any key form. In this case, the object-counting and object-comparison functions are never called; your application determines the formats and types of all tokens; and your application must interpret whose descriptor records created by the Apple Event Manager during the resolution of object specifier records. For more information, see “Handling Whose Tests,” which begins on page 6-41.s
  9822. Writing an Object-Counting Function
  9823.  
  9824. To handle object specifier records that specify tests, your application should provide an object-counting function (unless it specifies kAEIDoWhose as just described). Your object-counting function should be able to count the number of elements of a given object class in a given container. For example, if your application supports Apple event objects that belong to the object class cText in the Text suite, your application should provide an object-counting function that can count Apple event objects of each element class listed in the definition of cText in the Apple Event Registry: Standard Suites. In this case, your application should provide an object-counting function that can count the number of words, items, or characters in a text object.
  9825. You specify your object-counting function with the AESetObjectCallbacks function. Whenever it is resolving an object specifier record and it requires a count of the number of elements in a given container, the Apple Event Manager calls your object-counting function.
  9826. Here’s the declaration for a sample object-counting function:
  9827. FUNCTION MyCountObjects (desiredClass: DescType; 
  9828.                                  containerClass: DescType;
  9829.                                  containerToken: AEDesc; 
  9830.                                  VAR result: LongInt): OSErr;
  9831. The Apple Event Manager passes the following information to your object-counting function: the object class ID of the Apple event objects to count, the object class of their container, and a token identifying their container. (The container class can be useful if you want to use one token type for several object classes.) Your object-counting function uses this information to count the number of Apple event objects of the specified object class in the specified container. After counting the Apple event objects, your application should return the noErr result code and, in the result parameter, the number of Apple event objects counted. 
  9832. Listing 6-10 shows an application-defined function, MyCountObjects, that counts the number of objects for any object class supported by the application. 
  9833. Listing 6-10    An object-counting function
  9834.  
  9835. FUNCTION MyCountObjects (desiredClass: DescType; containerClass: DescType; 
  9836.                                  containerToken: AEDesc; VAR result: LongInt): OSErr;
  9837. VAR
  9838.     window: WindowPtr;
  9839. BEGIN
  9840.     result := 0;
  9841.     IF desiredClass = cWindow THEN
  9842.     BEGIN
  9843.         IF containerClass = typeNull THEN
  9844.         BEGIN
  9845.             {count the number of windows}
  9846.             window := FrontWindow;
  9847.             WHILE window <> NIL DO 
  9848.                 BEGIN
  9849.                     result := result + 1;
  9850.                     window := WindowPtr(WindowPeek(window)^.nextWindow);
  9851.                 END; {of while}
  9852.         END; 
  9853.         MyCountObjects := noErr;
  9854.     END {of cWindow}
  9855.     ELSE
  9856.         IF desiredClass = cWord THEN
  9857.             {count the number of words in the container}
  9858.             MyCountObjects := MyCountWords(containerClass, containerToken, 
  9859.                                                         result)
  9860.     ELSE
  9861.         IF desiredClass =     cParagraph THEN
  9862.             {count the number of paragraphs in the container}
  9863.             MyCountObjects := MyCountParas(containerClass, containerToken, 
  9864.                                                         result)
  9865.     ELSE
  9866.         {this app does not support any other object classes}
  9867.         MyCountObjects := kObjectClassNotFound;
  9868. END;  
  9869. Writing an Object-Comparison Function
  9870.  
  9871. To handle object specifier records that specify tests, your application should provide an object-comparison function (unless it specifies kAEIDoWhose as described on page 6-48). Your object-comparison function should be able to compare one Apple event object to another Apple event object or to another descriptor record. 
  9872. You specify your object-comparison function with the AESetObjectCallbacks function. Whenever it is resolving object specifier records and needs to compare the value of an Apple event object with another object or with data, the Apple Event Manager calls your object-comparison function.
  9873. Here’s the declaration for a sample object-comparison function:
  9874. FUNCTION MyCompareObjects (comparisonOperator: DescType; 
  9875.                                     object: AEDesc;
  9876.                                     objectOrDescToCompare: AEDesc; 
  9877.                                     VAR result: Boolean): OSErr;
  9878. The Apple Event Manager passes the following information to your object-comparison function: a comparison operator that specifies how the two objects should be compared, a token for the first Apple event object, and either a token that describes the Apple event object to compare or a descriptor record.
  9879. It is up to your application to interpret the comparison operators it receives. The meaning of comparison operators differs according to the Apple event objects being compared, and not all comparison operators apply to all object classes. After successfully comparing the Apple event objects, your object-comparison function should return the noErr result code and, in the result parameter, a Boolean value specifying TRUE if the result of the comparison is true and FALSE otherwise. If for any reason your comparison function is unable to compare the specified Apple event objects, it should return the result code errAEEventNotHandled; then the Apple Event Manager will try an alternative method of comparing the Apple event objects, such as calling the equivalent system object-comparison function, if one exists.
  9880. Your object-comparison function should be able to compare an Apple event object belonging to any object class with another Apple event object. Your function should also be able to compare two Apple event objects with different object classes, if appropriate. For example, an object-comparison function for a word-processing application might be asked to compare the First Name column of a specified row in a table with the first word on a specified page—that is, to compare an Apple event object of object class cColumn with an Apple event object of object class cWord. You must decide what kinds of comparisons make sense for your application.
  9881. The Apple Event Registry: Standard Suites defines standard comparison operators. Here is a list of the constants that correspond to these comparison operators:
  9882. CONST 
  9883.     kAEGreaterThan                            = '>   ';
  9884.     kAEGreaterThanEquals                            = '>=  ';
  9885.     kAEEquals                            = '=   ';    
  9886.     kAELessThan                            = '<   ';
  9887.     kAELessThanEquals                            = '<=  ';
  9888.     kAEBeginsWith                            = 'bgwt';
  9889.     kAEEndsWith                            = 'ends'; 
  9890.     kAEContains                            = 'cont';         
  9891. The comparison operators always relate the first operand to the second. For example, the constant kAEGreaterThan means that the object-comparison function should determine whether or not the value of the first operand is greater than the value of the second operand. For more information, see page 6-90.
  9892. Listing 6-11 shows an application-defined function, MyCompareObjects, that compares two Apple event objects of any object class supported by the application. 
  9893. Listing 6-11    Object-comparison function that compares two Apple event objects
  9894.  
  9895. FUNCTION MyCompareObjects (comparisonOperator: DescType; 
  9896.                                     theObject: AEDesc;
  9897.                                     objectOrDescToCompare: AEDesc; 
  9898.                                     VAR result: Boolean): OSErr;
  9899. BEGIN
  9900.     result := FALSE;
  9901.     {compare two objects for equivalence}
  9902.     IF comparisonOperator =                         kAEEquals THEN
  9903.         MyCompareObjects := MyCompEquals(theObject, 
  9904.                                                     objectOrDescToCompare, 
  9905.                                                     result)
  9906.     ELSE
  9907.         {compare two objects for greater than}
  9908.         IF comparisonOperator =                         kAEGreaterThan THEN
  9909.             MyCompareObjects := MyCompGreaterThan(theObject, 
  9910.                                                         objectOrDescToCompare,
  9911.                                                         result)
  9912.     ELSE
  9913.         {compare two objects for less than}
  9914.         IF comparisonOperator =                         kAELessThan THEN
  9915.             MyCompareObjects := MyCompLessThan(theObject, 
  9916.                                                         objectOrDescToCompare,
  9917.                                                         result)
  9918.     ELSE
  9919.     {this app does not support any other comparison operators}
  9920.         MyCompareObjects := errAEEventNotHandled;
  9921. END;
  9922. The MyCompareObjects function calls a separate application-defined routine for each comparison operator. In each case, the application-defined routine that actually performs the comparison can compare an Apple event object with either another Apple event object or with a descriptor record’s data. If for any reason the comparison cannot be performed, the MyCompareObjects function returns the result code errAEEventNotHandled.  
  9923. Writing Marking Callback Functions
  9924.  
  9925. Marking callback functions allow applications such as databases that can mark their own objects to take advantage of that capability when resolving object specifier records. Instead of returning a list of tokens for a group of Apple event objects that pass a test, your application can simply mark the Apple event objects and return a token that identifies how they have been marked. In this way, you can speed the resolution of complex object specifier records and reduce the amount of memory you need to allocate for tokens. 
  9926. The use of marking callback functions is optional and usually makes sense if (a) you can reasonably expect that the tokens created in the process of resolving some object specifier records might not all fit in memory at once or (b) your application already uses a marking mechanism. If you want the Apple Event Manager to use marking callback functions provided by your application, you must add the kAEIDoMarking constant to the value of the callbackFlags parameter for the AEResolve function. If for any reason your application cannot mark a requested set of Apple event objects, it should return errAEEventNotHandled as the result code, and the Apple Event Manager will attempt to continue resolving the object specifier record by some other method, such as using a system marking function, if one exists. 
  9927. If your application supports marking callback functions, it must provide three functions with declarations that match these examples:
  9928. FUNCTION MyGetMarkToken (containerToken: AEDesc; 
  9929.                                  containerClass: DescType; 
  9930.                                  VAR Result: AEDesc): OSErr;
  9931. FUNCTION MyMark (theToken: AEDesc; markToken: AEDesc; 
  9932.                       markCount: LongInt): OSErr;
  9933. FUNCTION MyAdjustMarks (newStart, newStop: LongInt; 
  9934.                                 markToken: AEDesc): OSErr;
  9935. For more detailed information about these sample declarations, see “Object Callback Functions,” which begins on page 6-96.
  9936. To resolve a given object specifier record with the aid of the marking callback functions provided by your application, the Apple Event Manager first calls your application’s mark token function (MyGetMarkToken), passing a token that identifies the container of the elements to be marked in the containerToken parameter and the container’s object class in the containerClass parameter. The mark token function returns a mark token. A mark token, like other tokens, can be a descriptor record of any type; however, unlike other tokens, it identifies the way your application marks Apple event objects during the current session while resolving a single test. A mark token does not identify a specific Apple event object; rather, it allows your application to associate a group of objects with a marked set.
  9937. After it receives the mark token, the Apple Event Manager can call your application’s object-marking function (MyMark) repeatedly to mark specific Apple event objects. The Apple Event Manager passes the following information to your marking function: in the theToken parameter, a token for the object to be marked (obtained from the appropriate object accessor function); in the markToken parameter, the current mark token; and in the markCount parameter, the mark count. The mark count indicates the number of times the Apple Event Manager has called the marking function for the current mark token. Your application should associate the mark count with each Apple event object it marks. 
  9938. When the Apple Event Manager needs to identify either a range of elements or the absolute position of an element in a group of Apple event objects that pass a test, it can use your application’s mark-adjusting function (MyAdjustMarks) to unmark objects that it has previously marked. For example, suppose an object specifier record specifies “any row in the table ‘MyCustomers’ for which the City column is ‘San Francisco.’” The Apple Event Manager first uses the appropriate object accessor routine to locate all the rows in the table for which the City column is “San Francisco” and calls the application’s marking function repeatedly to mark them. It then generates a random number between 1 and the number of rows it found that passed the test and calls the application’s mark-adjusting function to unmark all the rows whose mark count does not match the randomly generated number. If the randomly chosen row has a mark count value of 5, the Apple Event Manager passes the mark-adjusting function 5 in both the newStart parameter and the newStop parameter, and the current mark token in the markToken parameter. The newStart and newStop parameters identify the beginning and end of the new set of marked objects that the mark-adjusting function will create by unmarking those previously marked objects not included in the new set. 
  9939. When the Apple Event Manager calls your mark-adjusting function, your application must dispose of any data structures that it may have created to mark the previously marked objects. The Apple Event Manager calls your mark-adjusting function only once for a given mark token. 
  9940. A mark token is valid until the Apple Event Manager either disposes of it (by calling AEDisposeToken) or returns it as the result of the AEResolve function. If the final result of a call to the AEResolve function is a mark token, the Apple event objects currently marked for that mark token are those specified by the object specifier record passed to AEResolve, and your application can proceed to do whatever the Apple event has requested. Note that your application is responsible for disposing of a final mark token with a call to AEDisposeToken, just as for any other final token.
  9941. If your application supports marking, it should also provide a token disposal function. When the Apple Event Manager calls AEDisposeToken to dispose of a mark token that is not the final result of a call to AEResolve, the subsequent call to your token disposal function lets you know that you can unmark the Apple event objects marked with that mark token. A call to AEDisposeDesc to dispose of a mark token (which would occur if you did not provide a token disposal function) would leave the objects marked.   
  9942.  
  9943.  
  9944. Creating Object Specifier Records
  9945.  
  9946. If your application creates and sends Apple events that require the target application to locate Apple event objects, your application must create object specifier records for those events. This section describes how to use the four keyword-specified descriptor records described in “Descriptor Records Used in Object Specifier Records,” which begins on page 6-8, to specify the object class ID, container, key form, and key data for an object specifier record. 
  9947. Because the internal structure of an object specifier record is nearly identical to the internal structure of an AE record, it is possible to use AECreateList, AEPutPtr, and AEPutKeyDesc to add the four keyword-specified descriptor records to an AE record, then use AECoerceDesc to coerce the AE record to a descriptor record of type typeObjectSpecifier. However, it is usually preferable to use the CreateObjSpecifier function to accomplish the same goal. The CreateObjSpecifier function adds the keyword-specified descriptor records directly to an object specifier record, thus eliminating several steps that are required if you create an AE record first. The instructions that follow make use of CreateObjSpecifier. 
  9948. To specify the class ID for an object specifier record, your application can specify the appropriate class ID value as the desiredClass parameter for the CreateObjSpecifier function, which uses it to create a keyword-specified descriptor record with the keyword keyAEDesiredClass as part of an object specifier record. 
  9949. To specify the container for an object specifier record, your application must create a keyword-specified descriptor record with the keyword keyAEContainer that fully describes the container of the Apple event object. Because this container is usually another Apple event object, the container is usually specified by another object specifier record. 
  9950. To specify the complete container hierarchy of an Apple event object, your application must create a series of nested object specifier records, starting with the object specifier record for the Apple event object whose container is outermost. With the exception of this first object specifier record, each object specifier record specifies another object specifier record in the chain as a container. 
  9951. For example, Figure 6-2 on page 6-10 shows a series of nested object specifier records that specify the first row of a table named “Summary of Sales” in a document named “Sales Report.” The logical organization of the same object specifier records is summarized in Table 6-7.
  9952. Table 6-7    Nested object specifier records that describe a container hierarchy
  9953. Keyword    Descriptor type    Data    
  9954. keyAEDesiredClass    typeType    cRow    
  9955. keyAEContainer    typeObjectSpecifier    (see indented record)    
  9956. keyAEDesiredClass    typeType    cTable    
  9957. keyAEContainer    typeObjectSpecifier    (see indented record)    
  9958. keyAEDesiredClass    typeType    cDocument    
  9959. keyAEContainer    typeNull    Data handle is NIL    
  9960. keyAEKeyForm    typeEnumerated    formName    
  9961. keyAEKeyData    typeChar    "Sales Report"    
  9962. keyAEKeyForm    typeEnumerated    formName    
  9963. keyAEKeyData    typeChar    "Summary of Sales"    
  9964. keyAEKeyForm    typeEnumerated    formAbsolutePosition    
  9965. keyAEKeyData    typeLongInteger    1    
  9966.  
  9967. Note
  9968. The format used in Table 6-7 and similar tables throughout this chapter does not show the structure of nested object specifier records as they exist within an Apple event. Instead, this format shows what you would obtain after calling AEGetKeyDesc repeatedly to extract the object specifier records from an Apple event record.
  9969. When you call AEGetKeyDesc to extract a null descriptor record, AEGetKeyDesc returns a descriptor record of type AEDesc with a descriptor type of typeNull and a data handle whose value is 0.u
  9970. To specify the default container for an object specifier record (such as the container for the document in Table 6-7), you can use AECreateDesc to create a null descriptor record, which you can then pass in the theContainer parameter of the CreateObjSpecifier function. The CreateObjSpecifier function uses the null descriptor record to create a keyword-specified descriptor record with the keyword keyAEContainer as part of an object specifier record. 
  9971. The object specifier record that specifies the default container is always the first record you create in a series of nested object specifier records that specifies the complete container hierarchy for an Apple event object. Each one in the series uses the previously created object specifier record to specify its container. As with the null descriptor record, you can pass an object specifier record as the second parameter to the CreateObjSpecifier function, which uses it to create a keyword-specified descriptor record with the keyword keyAEContainer.
  9972. To specify the key form for an object specifier record, your application can specify a key form constant as the third parameter to the CreateObjSpecifier function, which uses it to create a keyword-specified descriptor record with the keyword keyAEKeyForm as part of an object specifier record. The standard key forms for object specifier records are summarized in Table 6-1 on page 6-12.
  9973. For example, the key form for the object specifier records in Table 6-7 that specify the document and the table is formName. In other words, the key data identifies the document and the table by their names. Similarly, the key form for the object specifier record in Table 6-7 that specifies the first row in the table is formAbsolutePosition. In other words, the key data identifies the position of the row compared to other rows in the same container.
  9974. To specify the key data for an object specifier record, your application must create a keyword-specified descriptor record with the keyword keyAEKeyData whose data handle refers to the appropriate data for the specified key form. You can use AECreateDesc, CreateCompDescriptor, CreateLogicalDescriptor, and related functions to create the descriptor record, which you can then pass in the fourth parameter of the CreateObjSpecifier function. The CreateObjSpecifier function uses this descriptor record to create a keyword-specified descriptor record with the keyword keyAEKeyData as part of an object specifier record.
  9975. Creating a Simple Object Specifier Record
  9976.  
  9977. This section shows how to use the CreateObjSpecifier function to create the object specifier record shown in Table 6-7. The CreateObjSpecifier function creates the necessary keyword-specified descriptor records for the class ID, container, key form, and key data and returns the resulting object specifier record as a descriptor record of type typeObjectSpecifier.
  9978. Listing 6-12 shows how the CreateObjSpecifier function creates an object specifier record from parameters that an application specifies.
  9979. Listing 6-12    Creating an object specifier record using CreateObjSpecifier
  9980.  
  9981. VAR
  9982.     desiredClass:                             DescType; 
  9983.     myObjectContainer:                             AEDesc; 
  9984.     myKeyForm:                             DescType; 
  9985.     myKeyDataDesc:                             AEDesc; 
  9986.     disposeInputs:                             Boolean; 
  9987.     myObjSpecRec:                             AEDesc;
  9988.     myErr:                            OSErr;
  9989.  
  9990. desiredClass := cRow;
  9991. myObjectContainer := MyGetContainer;
  9992. myKeyForm := formAbsolutePosition;
  9993. myKeyDataDesc := MyGetKeyData;
  9994. disposeInputs := TRUE;
  9995. {create an object specifier record}
  9996. myErr := CreateObjSpecifier(desiredClass, myObjectContainer, 
  9997.                                         myKeyForm, myKeyDataDesc, 
  9998.                                         disposeInputs, myObjSpecRec);
  9999. The code shown in Listing 6-12 demonstrates how an application might use the CreateObjSpecifier function to create four keyword-specified descriptor records as part of a descriptor record of type typeObjectSpecifier. The CreateObjSpecifier function returns a result code of noErr if the object specifier record was successfully created. The object specifier record returned in the myObjSpecRec parameter describes an Apple event object of the class specified by the desiredClass parameter, located in the container specified by the myObjectContainer parameter, with the key form specified by the myKeyForm parameter and key data specified by the myKeyDataDesc parameter. 
  10000. You can specify TRUE in the disposeInputs parameter if you want the CreateObjSpecifier function to dispose of the descriptor records you created for the myObjectContainer and myKeyDataDesc parameters. If you specify FALSE, then your application is responsible for disposing of these leftover descriptor records. 
  10001. Listing 6-13 shows an application-defined function that uses CreateObjSpecifier to create an object specifier record for the first row in the table named “Summary of Sales” in the document “Sales Report,” then uses the object specifier record returned in the myObjSpecRec parameter as the direct parameter for a Get Data event. 
  10002. Listing 6-13    Using CreateObjSpecifier in an application-defined function
  10003.  
  10004. FUNCTION MyRequestRowFromTarget (targetAddress: AEAddressDesc; 
  10005.                                             VAR reply: AppleEvent): OSErr;
  10006. VAR
  10007.     desiredClass:                                 DescType;
  10008.     myKeyForm:                                DescType;
  10009.     myObjectContainer:                                AEDesc;
  10010.     myObjSpecRec:                                 AEDesc;
  10011.     myKeyDataDesc:                                AEDesc;
  10012.     keyData:                                LongInt;
  10013.     theAppleEvent:                                AppleEvent;
  10014.     myErr:                                OSErr;
  10015.     ignoreErr:                                OSErr;
  10016.  
  10017. BEGIN
  10018.     {initialize (set to null descriptor records) the two descriptor records } 
  10019.     { that must eventually be disposed of}
  10020.     MyInit2DescRecs(myObjSpecRec, theAppleEvent);
  10021.  
  10022.     desiredClass := cRow;                                                        {specify the class}
  10023.                                                             {specify container for the row}
  10024.     myErr := MyCreateTableContainer(myObjectContainer, 
  10025.                                                 'Summary of Sales', 'Sales Report');
  10026.     IF myErr = noErr THEN 
  10027.     BEGIN
  10028.         myKeyForm := formAbsolutePosition;                                                    {specify the key form}
  10029.         keyData := 1;                                                    {specify the key data for row}
  10030.         myErr := AECreateDesc(typeLongInteger, @keyData, Sizeof(keyData), 
  10031.                                         myKeyDataDesc);
  10032.         IF myErr = noErr THEN
  10033.             {create the object specifier record}
  10034.             myErr := CreateObjSpecifier(desiredClass, myObjectContainer, 
  10035.                                                     myKeyForm, myKeyDataDesc, 
  10036.                                                     TRUE, myObjSpecRec);
  10037.         IF myErr = noErr THEN
  10038.             {myObjSpecRec now describes an Apple event object, and will become } 
  10039.             { direct parameter of a Get Data event; first create Get Data event}
  10040.             myErr := AECreateAppleEvent(kAECoreSuite, kAEGetData, targetAddress, 
  10041.                                                     kAutoGenerateReturnID, 
  10042.                                                     kAnyTransactionID, theAppleEvent);
  10043.  
  10044.  
  10045.  
  10046.         IF myErr = noErr THEN
  10047.             {add myObjSpecRec as the direct parameter of the Get Data event}
  10048.             myErr := AEPutParamDesc(theAppleEvent, keyDirectObject,
  10049.                                             myObjSpecRec);
  10050.         IF myErr = noErr THEN
  10051.             myErr := AESend(theAppleEvent, reply, kAEWaitReply + 
  10052.                                  kAENeverInteract, kAENormalPriority, 120, 
  10053.                                  @MyIdleFunction, NIL);
  10054.     END;
  10055.     ignoreErr := AEDisposeDesc(myObjSpecRec);
  10056.     ignoreErr := AEDisposeDesc(theAppleEvent);
  10057.     MyRequestRowFromTarget := myErr;
  10058. END;
  10059. The MyRequestRowFromTarget function shown in Listing 6-13 specifies the class ID as cRow, indicating that the desired Apple event object is a row in a table. It uses the application-defined function MyCreateTableContainer to create an object specifier record for the table that contains the row, passing “Summary of Sales” and “Sales Report” as the second and third parameters to identify the name of the table and the name of the document that contains the table. (The next section, “Specifying the Container Hierarchy,” explains how to construct the MyCreateTableContainer function.) It then specifies the key form as the constant formAbsolutePosition, which indicates that the key data specifies the position of the row within its container; sets the keyData variable to 1, indicating the first row, and uses AECreateDesc to create a descriptor record for the key data; and uses CreateObjSpecifier to create the object specifier record that describes the desired word.
  10060. The desired row is now fully described by the myObjSpecRec variable, which contains a descriptor record of type typeObjectSpecifier that contains the three nested object specifier records shown in Table 6-7 on page 6-56. After using AECreateAppleEvent to create a Get Data event, the MyRequestRowFromTarget function uses the AEPutParamDesc function to add the myObjSpecRec variable to the Get Data event as a direct parameter, then uses AESend to send the Get Data event.
  10061. Note that the MyRequestRowFromTarget function begins by using the application-defined function MyInit2DescRecs to set myObjSpecRec and theAppleEvent to null descriptor records. These two functions must be disposed of whether the function is successful or not. By setting them to null descriptor records, the function can dispose of them at the end regardless of where an error may have occurred.
  10062. Specifying the Container Hierarchy
  10063.  
  10064. Because the container for an object specifier record usually consists of a chain of other object specifier records that specify the container hierarchy, your application must create all the object specifier records in the chain, starting with the record for the outermost container. Listing 6-14 and Listing 6-15 demonstrate how to use the CreateObjSpecifier function to create the first two object specifier records in such a chain: the records for a document and a table. 
  10065. Listing 6-14    Specifying a document container
  10066.  
  10067. FUNCTION MyCreateDocContainer (VAR myDocContainer: AEDesc;
  10068.                                          docName: Str255): OSErr;
  10069. VAR
  10070.     myDocDescRec:                    AEDesc;
  10071.     nullDescRec:                     AEDesc;
  10072.     myErr:                    OSErr;
  10073. BEGIN
  10074.     {create a descriptor record for the name of the document}
  10075.     myErr := AECreateDesc(typeChar, @docName[1], 
  10076.                                      Length(docName), myDocDescRec);
  10077.     IF myErr = noErr THEN
  10078.         {create a null descriptor record}
  10079.         myErr := AECreateDesc(typeNull, NIL, 0, nullDescRec);
  10080.     IF myErr = noErr THEN
  10081.         {create an object specifier record to specify the }
  10082.         { document object}
  10083.         myErr := CreateObjSpecifier(cDocument, nullDescRec, 
  10084.                                              formName, myDocDescRec, TRUE, 
  10085.                                              myDocContainer);
  10086.     MyCreateDocContainer := myErr;
  10087. END;
  10088. The function MyCreateDocContainer in Listing 6-14 creates an object specifier record that identifies a document by name. It starts by using the AECreateDesc function to create two descriptor records: one of type typeChar for the name of the document, and one of type typeNull for the null descriptor record that specifies the default container (because the document is not contained in any other Apple event object). These two descriptor records can then be used as parameters for the CreateObjSpecifier function, which returns an object specifier record (that is, a descriptor record of type typeObjectSpecifier) in the myDocContainer variable. The object specifier record specifies an Apple event object of the object class cDocument in the container specified by the nullDescRec variable with a key form of formName and the key data specified by the myDocDescRec variable. This object specifier can be used by itself to specify a document, or it can be used to specify the container for another Apple event object.
  10089. Listing 6-15 shows an application-defined function, MyCreateTableContainer, that creates an object specifier record describing a table contained in a document. 
  10090. Listing 6-15    Specifying a table container
  10091.  
  10092. FUNCTION MyCreateTableContainer (VAR myTableContainer: AEDesc;
  10093.                                             tableName: Str255;
  10094.                                             docName: Str255): OSErr;
  10095. VAR
  10096.     myDocDescRec:                            AEDesc;
  10097.     myTableDescRec:                            AEDesc;
  10098.     myErr:                            OSErr;
  10099. BEGIN
  10100.     {create a container for the document}
  10101.     myErr := MyCreateDocContainer(myDocDescRec, docName);
  10102.     IF myErr = noErr THEN
  10103.     BEGIN
  10104.         {create the table container, }
  10105.         { first specify the descriptor record for the key data}
  10106.         myErr := AECreateDesc(typeChar, @tableName[1], 
  10107.                                         Length(tableName), myTableDescRec);
  10108.         IF myErr = noErr THEN
  10109.             myErr := CreateObjSpecifier(cTable, myDocDescRec,
  10110.                                                 formName, myTableDescRec, 
  10111.                                                 TRUE, myTableContainer);
  10112.     END;
  10113.     MyCreateTableContainer := myErr;
  10114. END;
  10115. The function MyCreateTableContainer in Listing 6-15 starts by using the function MyCreateDocContainer from Listing 6-14 to create an object specifier record that identifies the table’s container—the document in which the table is located. Then it uses the AECreateDesc function to create a descriptor record for the key data—a name that, when combined with the key form formName, will identify the table in the document. The object specifier record for the document and the descriptor record specifying the table’s name are passed to the function CreateObjSpecifier. It returns an object specifier record in the myTableContainer parameter that specifies an Apple event object of the object class cTable in the container specified by the MyDocDescRec variable with a key form of formName and the key data specified by the myTableDescRec variable. This object specifier record can be used by itself to specify a table, or it can be used to specify the container for another Apple event object.
  10116. Listing 6-13 uses the MyCreateTableContainer function shown in Listing 6-15 to specify the container hierarchy illustrated in Table 6-7 on page 6-56. The nested object specifier records shown in Table 6-7 use the key forms formName and formRelativePosition. You can create key data for the key forms formPropertyID, formUniqueID, and formRelativePosition using similar techniques.    
  10117. Specifying a Property
  10118.  
  10119. The key form formPropertyID allows your application to specify key data identifying a property of the object specified as a container. For example, an object specifier record that identifies the font property of a word specifies cProperty as the class ID, an object specifier record for the word as the property’s container, formPropertyID as the key form, and the constant pFont as the key data. 
  10120. Note that an object specifier record that identifies a property does not include a value for the property, such as Palatino. The value of a property is returned or set as a parameter of an Apple event. For example, an application that sends a Get Data event to get the pFont property of a word receives a value such as Palatino in the keyAEResult parameter of the reply event, and an application that sends a Set Data event to change the pFont property of a word specifies a font in the keyAEData parameter of the Set Data event. 
  10121. To specify the key data for a key form of formPropertyID, your application must create a descriptor record of typeType whose data consists of a constant specifying a property. You can use AECreateDesc to create a descriptor record that specifies the constant for a property, then use CreateObjSpecifier to add the descriptor record to an object specifier record as a keyword-specified descriptor record with the keyword keyAEKeyData.
  10122. For more information about object specifier records that specify a property, see “Key Data for a Property ID” on page 6-13.
  10123. Specifying a Relative Position
  10124.  
  10125. The key form formRelativePosition allows your application to specify key data identifying an element or a set of elements that are immediately before or after the specified container. For example, if the container is a table, you could use a key form of formRelativePosition to specify the paragraph before or after the table. 
  10126. To specify the key data for a key form of formRelativePosition, your application must create a descriptor record of typeEnumerated whose data consists of a constant specifying either the element after (kAENext) or the element before (kAEPrevious) the specified container.
  10127. You can use AECreateDesc to create a descriptor record that specifies one of these constants, then use CreateObjectSpecifier to add it to an object specifier record as a keyword-specified descriptor record with the keyword keyAEKeyData.
  10128. For more information about object specifier records that specify a relative position, see “Key Data for Relative Position” on page 6-15.   
  10129. Creating a Complex Object Specifier Record
  10130.  
  10131. This section describes how to create object specifier records that specify a test or a range. You can specify the object class ID for these object specifier records the same way you would for any other object specifier record. When you create the other three keyword-specified descriptor records, however, you can use additional Apple Event Manager routines and descriptor types to specify any combination of Apple event objects. 
  10132. Specifying a Test
  10133.  
  10134. The key form formTest allows your application to specify key data that identifies one or more elements in the specified container that pass a test. To do so, your application must construct several interconnected descriptor records that specify comparisons and, if necessary, logical expressions. 
  10135. For example, to specify “the first row in which the First Name column equals ‘John’ and the Last Name column equals ‘Chapman’ in the table ‘MyAddresses’ of the database ‘SurfDB,’” your application must construct an object specifier record whose key data describes a logical expression that applies the logical operator AND to two separate comparisons for each row: a comparison of the First Name column to the word “John” and a comparison of the Last Name column to the word “Chapman.” 
  10136. The logical organization of the data for the object specifier record that specifies this test is summarized in Table 6-8 and Table 6-9. (It is also illustrated in Figure 6-3 and Figure 6-4, beginning on page 6-18.) The listings in the remainder of this section demonstrate how to create this object specifier record. For general information about the organization of key data for a test, see “Key Data for a Test,” which begins on page 6-15.
  10137. Table 6-8    Object specifier record for the first row that meets a test in the table named “MyAddresses”
  10138. Keyword    Descriptor type    Data    
  10139. keyAEDesiredClass    typeType    cRow    
  10140. keyAEContainer    typeObjectSpecifier    (see indented record)    
  10141. keyAEDesiredClass    typeType    cRow    
  10142. keyAEContainer    typeObjectSpecifier    (see indented record)    
  10143. keyAEDesiredClass    typeType    cTable    
  10144. keyAEContainer    typeObjectSpecifier    (see indented record)    
  10145. keyAEDesiredClass    typeType    cDatabase    
  10146. keyAEContainer    typeNull    Data handle is NIL    
  10147. keyAEKeyForm    typeEnumerated    formName    
  10148. keyAEKeyData    typeChar    "SurfDB"    
  10149. keyAEKeyForm    typeEnumerated    formName    
  10150. keyAEKeyData    typeChar    "MyAddresses"    
  10151. keyAEKeyForm    typeEnumerated    formTest    
  10152. keyAEKeyData    typeLogicalDescriptor    (see Table 6-9)    
  10153. keyAEKeyForm    typeEnumerated    formAbsolutePosition    
  10154. keyAEKeyData    typeLongInteger    1    
  10155.  
  10156. Table 6-9    Logical descriptor record that specifies a test
  10157. Keyword    Descriptor type    Data    
  10158. keyAELogicalOperator    typeEnumerated    kAEAnd    
  10159. keyAELogicalTerms    typeAEList    (see indented records)    
  10160.     typeCompDescriptor    (see indented record)    
  10161. keyAECompOperator    typeType    kAEEquals    
  10162. keyAEObject1    typeObjectSpecifier    (see indented record)    
  10163. keyAEDesiredClass    typeType    cColumn    
  10164. keyAEContainer    typeObjectBeingExamined    Data handle is NIL    
  10165. keyAEKeyForm    typeEnumerated    formName    
  10166. keyAEKeyData    typeChar    "First Name"    
  10167. keyAEObject2    typeChar    "John"    
  10168.     typeCompDescriptor    (see indented record)    
  10169. keyAECompOperator    typeType    kAEEquals    
  10170. keyAEObject1    typeObjectSpecifier    (see indented record)    
  10171. keyAEDesiredClass    typeType    cColumn    
  10172. keyAEContainer    typeObjectBeingExamined    Data handle is NIL    
  10173. keyAEKeyForm    typeEnumerated    formName    
  10174. keyAEKeyData    typeChar    "Last Name"    
  10175. keyAEObject2    typeChar    "Chapman"    
  10176.  
  10177. Because both the database and the table shown in Table 6-8 are specified by name, it would be convenient to have an application-defined routine that creates an object specifier record that uses the key form formName. The MyCreateFormNameObjSpecifier function shown in Listing 6-16 can be used for this purpose.
  10178. Listing 6-16    Creating an object specifier record with the key form formName
  10179.  
  10180. FUNCTION MyCreateFormNameObjSpecifier
  10181.                                 (class: DescType; container: AEDesc; 
  10182.                                  keyDataName: str255; 
  10183.                                  VAR resultObjSpecRec: AEDesc): OSErr;
  10184. VAR
  10185.     keyDataDescRec: AEDesc;
  10186.     myErr:                      OSErr;
  10187. BEGIN
  10188.     myErr := AECreateDesc(typeChar, @keyDataName[1], 
  10189.                                      Length(keyDataName), keyDataDescRec);
  10190.     IF myErr = noErr THEN
  10191.         myErr := CreateObjSpecifier(class, container, formName,
  10192.                                                 keyDataDescRec, TRUE,
  10193.                                                 resultObjSpecRec);
  10194.     MyCreateFormNameObjSpecifier := myErr;
  10195. END;
  10196. The MyCreateFormNameObjSpecifier function shown in Listing 6-16 returns, in the resultObjSpecRec parameter, an object specifier record that describes an Apple event object of the class specified by the class parameter, located in the container specified by the container parameter, with the key form formName and key data specified by the keyDataName parameter. This function is used in Listing 6-19 on page 6-70 to create object specifier records that use the key form formName for the database and the table. 
  10197. The nested object specifier records shown in Table 6-9 specify “the rows in which the First Name column equals ‘John’ and the Last Name column equals ‘Chapman.’” To identify the rows that pass this test, the Apple Event Manager needs to evaluate two comparisons: the comparison of each row of the First Name column to the word “John,” and the comparison of each row of the Last Name column to the word “Chapman.”
  10198. The Apple Event Manager uses the information in comparison descriptor records to compare the specified elements in a container, one at a time, either to another Apple event object or to the data associated with a descriptor record. The two comparison descriptor records you need to create for this example are summarized in Table 6-9 on page 6-66. 
  10199. You can use the CreateCompDescriptor function to create a comparison descriptor record, or you can create an AE record and use AECoerceDesc to coerce it to a comparison descriptor record. Listing 6-17 shows an example of an application-defined routine that creates an object specifier record and a descriptor record of typeChar, then uses the CreateCompDescriptor function to add them to a comparison descriptor record. 
  10200. Listing 6-17    Creating a comparison descriptor record
  10201.  
  10202. FUNCTION MyCreateComparisonDescRec (VAR compDesc: AEDesc;
  10203.                                                 colName: str255; 
  10204.                                                 name: str255): OSErr;
  10205. VAR
  10206.     logicalContainer, colNameDesc, nameDesc:                                                         AEDesc;
  10207.     myObjectExaminedContainer:                                                         AEDesc;
  10208.     myErr:                                                        OSErr;
  10209. BEGIN
  10210.     {create the object specifier record for keyAEObject1; }
  10211.     { first create container}
  10212.     myErr := AECreateDesc(typeObjectBeingExamined, NIL, 0,
  10213.                                     myObjectExaminedContainer);
  10214.     {create key data}
  10215.     IF myErr = noErr THEN
  10216.         myErr := AECreateDesc(typeChar, @colName[1],
  10217.                                      Length(colName), colNameDesc);
  10218.     {now create the object specifier record}
  10219.     IF myErr = noErr THEN
  10220.         myErr := CreateObjSpecifier(cColumn,
  10221.                                              myObjectExaminedContainer, 
  10222.                                              formName, colNameDesc, TRUE,
  10223.                                              logicalContainer);
  10224.     {create the descriptor record for keyAEObject2}
  10225.     IF myErr = noErr THEN
  10226.         myErr := AECreateDesc(typeChar, @name[1], Length(name), 
  10227.                                      nameDesc);
  10228.     {create the first logical term (comp descriptor record)}
  10229.     IF myErr = noErr THEN
  10230.         myErr := CreateCompDescriptor(kAEEquals, logicalContainer,
  10231.                                                 nameDesc, TRUE, compDesc);
  10232.     MyCreateComparisonDescRec := myErr;
  10233. END; 
  10234. The MyCreateComparisonDescRec function takes two strings and uses them to create a comparison descriptor record. The string passed in the second parameter specifies the name of the column whose contents should be compared to the string passed in the third parameter. First, the MyCreateComparisonDescRec function uses AECreateDesc to create a descriptor record of typeObjectBeingExamined, which is returned in the variable myObjectExaminedContainer. Next, AECreateDesc creates a descriptor record of descriptor type typeChar, whose data consists of the string in the variable colName, and which is returned in the variable colNameDesc. The code then passes the variables myObjectExaminedContainer and colNameDesc to the CreateObjSpecifier function, which uses them to create an object specifier record, returned in the logicalContainer variable, that becomes the keyword-specified descriptor record with the keyword keyAEObject1.
  10235. Next, the MyCreateComparisonDescRec function uses AECreateDesc and the name parameter to create the descriptor record for keyAEObject2, which AECreateDesc returns in the nameDesc variable. Finally, the code passes the constant kAEEquals, the variable logicalContainer, and the variable nameDesc to the CreateCompDescriptor function, which creates a comparison descriptor record that allows the Apple Event Manager (with the help of object-comparison functions provided by the server application) to determine whether the specified column in the row currently being checked equals the specified string. 
  10236. You can use the MyCreateComparisonDescRec function to create both the descriptor records of type typeCompDescriptor shown in Table 6-9 on page 6-66. These descriptor records provide two logical terms for a logical descriptor record. The entire logical descriptor record corresponds to the logical expression “the First Name column equals ‘John’ AND the Last Name column equals ‘Chapman.’”  
  10237. You can use the CreateLogicalDescriptor function to create a logical descriptor record, or you can create an AE record and use the AECoerceDesc function to coerce it to a comparison descriptor record. Listing 6-18 shows an application-defined function that adds two comparison descriptor records to a descriptor list, then uses the CreateLogicalDescriptor function to create a logical descriptor record whose logical terms are the two comparison descriptor records.
  10238. Listing 6-18    Creating a logical descriptor record
  10239.  
  10240. FUNCTION MyCreateLogicalDescRec (VAR compDesc1, compDesc2: AEDesc;
  10241.                                             logicalOperator: DescType;
  10242.                                             VAR logicalDesc: AEDesc): OSErr;
  10243. VAR
  10244.     logicalTermsList: AEDescList;
  10245.     myErr:                         OSErr;
  10246. BEGIN
  10247.     {create a logical descriptor record that contains two }
  10248.     { comparison descriptor records}
  10249.     {first create a list}
  10250.     myErr := AECreateList(NIL, 0, FALSE, logicalTermsList);
  10251.     IF myErr = noErr THEN
  10252.         myErr := AEPutDesc(logicalTermsList, 1, compDesc1);
  10253.     IF myErr = noErr THEN
  10254.         myErr := AEPutDesc(logicalTermsList, 2, compDesc2);
  10255.     IF myErr = noErr THEN
  10256.         myErr := AEDisposeDesc(compDesc1);
  10257.     IF myErr = noErr THEN
  10258.         myErr := AEDisposeDesc(compDesc2);
  10259.     IF myErr = noErr THEN
  10260.         myErr := CreateLogicalDescriptor(logicalTermsList,
  10261.                                                     logicalOperator, TRUE,
  10262.                                                     logicalDesc);
  10263.     MyCreateLogicalDescRec := myErr;
  10264. END;
  10265. Listing 6-19 uses the application-defined functions shown in Listing 6-16, Listing 6-17, and Listing 6-18 to build the object specifier record illustrated in Table 6-8 and Table 6-9.  
  10266. Listing 6-19    Creating a complex object specifier record
  10267.  
  10268. FUNCTION MyCreateObjSpecRec (VAR theResultObj: AEDesc): OSErr;
  10269. VAR
  10270.     nullContainer, databaseContainer, tableContainer:                                                                     AEDesc;
  10271.     compDesc1, compDesc2:                                                                     AEDesc;
  10272.     logicalTestDesc, rowTestContainer, rowOffset:                                                                     AEDesc;
  10273.     myErr:                                                                     OSErr;
  10274.  
  10275.  
  10276.  
  10277.  
  10278. BEGIN
  10279.     {create a null container}
  10280.     myErr := AECreateDesc(typeNull, NIL, 0, nullContainer);
  10281.     {create a container for the database}
  10282.     IF myErr = noErr THEN
  10283.         myErr := MyCreateFormNameObjSpecifier(cDatabase, nullContainer,
  10284.                                                           'SurfDB', databaseContainer);
  10285.     {create a container for the table}
  10286.     IF myErr = noErr THEN
  10287.         myErr := MyCreateFormNameObjSpecifier(cTable, databaseContainer, 
  10288.                                                           'MyAddresses', tableContainer);
  10289.     {create a container for the row--an object specifier record that }
  10290.     { specifies a test (the row whose First Name column = 'John' and }
  10291.     { Last Name column = 'Chapman')}
  10292.  
  10293.     {create the first comparison descriptor record}
  10294.     IF myErr = noErr THEN
  10295.         myErr := MyCreateComparisonDescRec(compDesc1, 'First Name', 'John'); 
  10296.     {create the second comparison descriptor record}
  10297.     IF myErr = noErr THEN
  10298.         myErr := MyCreateComparisonDescRec(compDesc2, 'Last Name', 'Chapman'); 
  10299.  
  10300.     {create the logical descriptor record}
  10301.     IF myErr = noErr THEN
  10302.         myErr := MyCreateLogicalDescRec(compDesc1, compDesc2, kAEAND, 
  10303.                                                     logicalTestDesc);
  10304.  
  10305.     {now create the object specifier record that specifies the test}
  10306.     IF myErr = noErr THEN
  10307.         myErr := CreateObjSpecifier(cRow, tableContainer, formTest,
  10308.                                              logicalTestDesc, TRUE, rowTestContainer);
  10309.  
  10310.     {create the object specifier record for the Apple event object}
  10311.     {first, create the descriptor record for the key data}
  10312.     IF myErr = noErr THEN
  10313.         myErr := CreateOffsetDescriptor (1, rowOffset);
  10314.     {now create the object specifier record}
  10315.     IF myErr = noErr THEN
  10316.         myErr := CreateObjSpecifier (cRow, rowTestContainer, 
  10317.                                                 formAbsolutePosition, rowOffset, 
  10318.                                                 TRUE, theResultObj);
  10319.     MyCreateObjSpecRec := myErr;
  10320. END;
  10321. The MyCreateObjSpecRec function shown in Listing 6-19 begins by using AECreateDesc to create a null descriptor record, then uses the MyCreateFormNameObjSpecifier function (shown in Listing 6-16) to specify the default container for the database named “SurfDB.” The code then calls the MyCreateFormNameObjSpecifier function again, this time passing the object specifier record for SurfDB to specify the container for the table “MyAddresses.” The next two calls are both to the MyCreateComparisonDescRec function (shown in Listing 6-17), which creates the comparison descriptor records that allow the Apple Event Manager to compare the First Name column and Last Name column to the names “John” and “Chapman,” respectively. The next call passes these two comparison descriptor records to the MyCreateLogicalDescRec function (shown in Listing 6-18) in the compDesc1 and compDesc2 variables. 
  10322. Now all the components of the logical descriptor record are ready to assemble. The next call, to CreateObjSpecifier, specifies the logical descriptor record in the logicalTestDesc variable as the key data for the object specifier record that specifies the test. A call to the Apple Event Manager routine CreateOffsetDescriptor then creates an offset descriptor record that contains the integer 1. Finally, the code passes the offset descriptor record to the CreateObjSpecifier function in the rowOffset variable to create the final object specifier record, which describes the requested row as the first row that passes the test.
  10323. The CreateOffsetDescriptor function creates a descriptor record of type typeLongInteger that can be used as the key data with a key form of formAbsolutePosition to indicate an element’s offset within its container. A positive integer indicates an offset from the beginning of the container (the first element has an offset of 1), and a negative integer indicates an offset from the end of the container (the last element has an offset of –1). Using CreateOffsetDescriptor accomplishes the same thing as setting a variable to an integer and passing the variable to AECreateDesc to create a descriptor record of type typeLongInteger.    
  10324. Specifying a Range
  10325.  
  10326. The key form formRange allows your application to specify key data that identifies a range of elements in the specified container. To do so, your application must first create a range descriptor record. The Apple Event Manager uses a range descriptor record to identify the two Apple event objects that specify the beginning and end of a range of elements. 
  10327. For example, an object specifier record for a range of text in a document could specify the table named “Summary of Sales” as the first boundary object and the figure named “Best-Selling Widgets for 1991” as the second boundary object for a range that consists of all the text between the table and the figure. Any word processor that keeps track of the relative positions of text, tables, and figures should be capable of supporting such a request. 
  10328. Table 6-10 summarizes the logical organization of the data for the object specifier record that specifies this range. For general information about the organization of data within a range descriptor record, see “Key Data for a Range” on page 6-20.
  10329. Table 6-10    A range descriptor record
  10330. Keyword    Descriptor type    Data    
  10331. keyAERangeStart    typeObjectSpecifier    (see indented record)    
  10332. keyAEDesiredClass    typeType    cTable    
  10333. keyAEContainer    typeCurrentContainer    Data handle is NIL    
  10334. keyAEKeyForm    typeEnumerated    formName    
  10335. keyAEKeyData    typeChar    "Summary of Sales"    
  10336. keyAERangeStop    typeObjectSpecifier    (see indented record)    
  10337. keyAEDesiredClass    typeType    cFigure    
  10338. keyAEContainer    typeCurrentContainer    Data handle is NIL    
  10339. keyAEKeyForm    typeEnumerated    formName    
  10340. keyAEKeyData    typeChar    "Best-Selling Widgets 
  10341. for 1991"    
  10342.  
  10343. You can use the CreateRangeDescriptor function to create a range descriptor record, or you can create an AE record and use AECoerceDesc to coerce it to a range descriptor record. Listing 6-20 provides an example of an application-defined routine that creates two object specifier records, then uses the CreateRangeDescriptor function to add them to a range descriptor record.
  10344. The container for the boundary objects in the range descriptor record created by 
  10345. Listing 6-20 is the same as the container for the range itself. The object specifier record for the range’s container is added to an object specifier record of key form formRange at the same time that the range descriptor record is added as key data. The container for the two boundary objects can therefore be specified in the range descriptor record by a descriptor record of type typeCurrentContainer whose data handle has the value NIL. The Apple Event Manager interprets this as a placeholder for the range’s container when it is resolving the range descriptor record.
  10346. Listing 6-20    Creating a range descriptor record
  10347.  
  10348. FUNCTION MyCreateRangeDescriptor (VAR rangeDescRec: AEDesc): OSErr;
  10349. VAR
  10350.     rangeStart:                             AEDesc;
  10351.     rangeEnd:                            AEDesc;
  10352.     currentContainer:                            AEDesc;
  10353.     tableNameDescRec    :                        AEDesc;
  10354.     figureNameDescRec    :                        AEDesc;
  10355.     myErr:                            OSErr;
  10356. BEGIN
  10357. {create the object specifier record for the start of the range }
  10358. { (the table named 'Summary of Sales' in 'MyDoc' document)}
  10359.  
  10360.     {create a descriptor record of type typeCurrentContainer}
  10361.     myErr := AECreateDesc(typeCurrentContainer, NIL, 0, currentContainer);
  10362.  
  10363.     {create the object specifier record}
  10364.     IF myErr = noErr THEN
  10365.         myErr := MyCreateNameDescRec(tableNameDescRec, 
  10366.                                                 'Summary of Sales');
  10367.     IF myErr = noErr THEN
  10368.     myErr := CreateObjSpecifier(cTable, currentContainer, formName,
  10369.                                              tableNameDescRec, FALSE, rangeStart);
  10370.     
  10371.     myErr := AEDisposeDesc(tableNameDescRec);
  10372.     {create the object specifier record for the end of the range }
  10373.     { (the figure named 'Best-Selling Widgets...' in 'MyDoc') }
  10374.     IF myErr = noErr THEN
  10375.         myErr := MyCreateNameDescRec(figureNameDescRec, 
  10376.                                                 'Best-Selling Widgets for 1991');
  10377.  
  10378.     IF myErr = noErr THEN
  10379.         myErr := CreateObjSpecifier(cFigure, currentContainer, formName,
  10380.                                              figureNameDescRec, TRUE, rangeEnd);
  10381.  
  10382.     {now create the range descriptor record}
  10383.     IF myErr = noErr THEN
  10384.         myErr := CreateRangeDescriptor(rangeStart, rangeEnd, TRUE, 
  10385.                                                     rangeDescRec);
  10386.     MyCreateRangeDescriptor := myErr;
  10387. END;
  10388. After creating a descriptor record of type typeCurrentContainer and a descriptor record for the first table’s name, Listing 6-20 uses the CreateObjSpecifier function to create an object specifier record that identifies the beginning of the range. The parameters to CreateObjSpecifier specify that the beginning of the range is an Apple event object of the object class cTable in the current container, with a key form of formName and key data that identifies the table by name. A second call to CreateObjSpecifier creates the object specifier record that identifies the end of the range—an Apple event object of the cFigure object class in the current container, with a key form of formName and key data that identifies the figure by name. Finally, the code in Listing 6-20 uses the CreateRangeDescriptor function to create the range descriptor record, using the two previously created object specifier records to specify the beginning and end of the range.  
  10389.  
  10390. Reference to Resolving and Creating Object Specifier Records
  10391.  
  10392. This section describes the Apple Event Manager routines your application can use to resolve and create object specifier records. It also describes application-defined object accessor functions and object callback functions that your application can provide for use by the Apple Event Manager in resolving object specifier records. 
  10393. The first section, “Data Structures Used in Object Specifier Records,” summarizes the descriptor types and associated data that can be used in an object specifier record. “Routines for Resolving and Creating Object Specifier Records,” which begins on page 6-77, describes the Apple Event Manager routines you use to initialize the Object Support Library, resolve object specifier records, set and manipulate object accessor functions, deallocate memory for tokens, and create object specifier records. “Application-Defined Routines,” which begins on page 6-94, describes the object accessor functions and object callback functions that a server application can provide.
  10394. Data Structures Used in Object Specifier Records
  10395.  
  10396. The data for object specifier records can be specified using a variety of descriptor records and descriptor types. These are described in detail in “Descriptor Records Used in Object Specifier Records,” which begins on page 6-8, and summarized in Table 6-11.
  10397. Table 6-11    Keyword-specified descriptor records for typeObjectSpecifier(continued)(continued)
  10398. Keyword    Descriptor type    Data    
  10399. keyAEDesiredClass    typeType    Object class ID    
  10400. keyAEContainer    typeObjectSpecifier    Object specifier record    
  10401.     typeNull    Data handle is NIL. Specifies the default container at the top of the container hierarchy.    
  10402.     typeObjectBeingExamined    Data handle is NIL. Specifies the container for elements that are tested one at a time; used only with formTest.     
  10403.     typeCurrentContainer    Data handle is NIL. Specifies a container for an element that demarcates one boundary in a range. Used only with formRange.     
  10404. keyAEKeyForm    typeEnumerated    formPropertyID
  10405. formName
  10406. formUniqueID
  10407. formAbsolutePosition
  10408. formRelativePosition
  10409. formTest
  10410. formRange
  10411. formWhose     
  10412. keyAEKeyData        (See indented key forms)    
  10413. for formPropertyID    typeType    Property ID for an element’s property    
  10414. for formName    typeChar or other text type    Element’s name    
  10415. for formUniqueID    Any appropriate type    Element’s unique ID    
  10416. for formAbsolutePosition    typeLongInteger    Offset from beginning (positive) or end (negative) of container    
  10417.     typeAbsoluteOrdinal    kAEFirst 
  10418. kAEMiddle
  10419. kAELast
  10420. kAEAny
  10421. kAEAll    
  10422. for formRelativePosition    typeEnumerated    kAENext
  10423. kAEPrevious     
  10424. for formTest    typeCompDescriptor    (See Table 6-2 on page 6-16)    
  10425.     typeLogicalDescriptor    (See Table 6-3 on page 6-17)    
  10426. for formRange    typeRangeDescriptor    (See Table 6-4 on page 6-20)    
  10427. for formWhose    typeWhoseDescriptor    (See Table 6-5 on page 6-42)    
  10428.  
  10429. Routines for Resolving and Creating Object Specifier Records
  10430.  
  10431. This section describes routines for initializing the Object Support Library, resolving object specifier records, setting and manipulating object accessor functions, deallocating memory for tokens, and creating object specifier records.
  10432. Initializing the Object Support Library
  10433.  
  10434. You should call the AEObjectInit function to initialize the Apple Event Manager routines that handle object specifier records and Apple event objects. To make these routines available to your application with version 1.01 and earlier versions of the Apple Event Manager, you must also link the Apple Event Object Support Library with your application when you build it.
  10435. AEObjectInit
  10436.  
  10437. You use the AEObjectInit function to initialize the Object Support Library.
  10438. FUNCTION AEObjectInit: OSErr; 
  10439. DESCRIPTION
  10440. You must call this function before calling any of the Apple Event Manager routines that describe or manipulate Apple event objects.
  10441. RESULT CODESnoErr    0    No error occurred    
  10442. memFullErr    –108    Not enough room in heap zone    
  10443. errAENewerVersion    –1706    Need a newer version of the Apple Event Manager    
  10444.  
  10445. Setting Object Accessor Functions and Object Callback Functions
  10446.  
  10447. The Apple Event Manager provides two routines that allow you to specify the object accessor functions and object callback functions provided by your application. The AEInstallObjectAccessor function adds an entry for an object accessor function to either the application’s object accessor dispatch table or the system object accessor dispatch table. The AESetObjectCallbacks function allows you to specify the object callback functions to be called for your application. 
  10448. AEInstallObjectAccessor
  10449.  
  10450. You can use the AEInstallObjectAccessor function to add an entry for an object accessor function to either the application’s object accessor dispatch table or the system object accessor dispatch table.  
  10451. FUNCTION AEInstallObjectAccessor (desiredClass: DescType; 
  10452.                                              containerType: DescType; 
  10453.                                              theAccessor: AccessorProcPtr; 
  10454.                                              accessorRefcon: LongInt; 
  10455.                                              isSysHandler: Boolean): OSErr;
  10456. desiredClass
  10457. The object class of the Apple event objects to be located by the object accessor function for this table entry.
  10458. containerType
  10459. The descriptor type of the token used to specify the container for the desired objects. The object accessor function finds objects in containers specified by tokens of this type.
  10460. theAccessor
  10461. A pointer to the object accessor function for this table entry. Note that an object accessor function listed in the system dispatch table must reside in the system heap; thus, if the value of the isSysHandler parameter is TRUE, the theAccessor parameter should point to a location in the system heap. Otherwise, if you put your system object accessor function in your application heap, you must call AERemoveObjectAccessor to remove the function before your application terminates.
  10462. accessorRefcon
  10463. A reference constant passed by the Apple Event Manager to the object accessor function whenever the function is called. If your object accessor function doesn’t use a reference constant, use 0 as the value of this parameter. To change the value of the reference constant, you must call AEInstallObjectAccessor again.
  10464. isSysHandler
  10465. A value that specifies the object accessor dispatch table to which the entry is added. If the value of isSysHandler is TRUE, the Apple Event Manager adds the entry to the system object accessor dispatch table. Entries in the system object accessor dispatch table are available to all applications running on the same computer. If the value is FALSE, the Apple Event Manager adds the entry to your application’s object accessor table. When searching for object accessor functions, the Apple Event Manager searches the application’s object accessor dispatch table first; it searches the system object accessor dispatch table only if the necessary function is not found in your application’s object accessor dispatch table.
  10466. DESCRIPTION
  10467. The AEInstallObjectAccessor function adds an entry to either the application or system object accessor dispatch table. You must supply parameters that specify the object class of the Apple event objects that the object accessor function can locate, the descriptor type of tokens for containers in which the object accessor function can locate objects, the address of the object accessor function for which you are adding an entry, and whether the entry is to be added to the system object accessor dispatch table or your application’s object accessor dispatch table. You can also specify a reference constant that the Apple Event Manager passes to your object accessor function each time the Apple Event Manager calls the function.
  10468. RESULT CODESnoErr    0    No error occurred    
  10469. paramErr    –50    The handler pointer is NIL or odd, or AEObjectInit was not called before this function    
  10470.  
  10471. SEE ALSO
  10472. For more information about installing object accessor functions, see “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 6-21.  
  10473. For a description of the AERemoveObjectAccessor function, see page 6-84.
  10474. AESetObjectCallbacks
  10475.  
  10476. You can use the AESetObjectCallbacks function to specify the object callback functions to be called for your application.  
  10477. FUNCTION AESetObjectCallbacks (myCompareProc, myCountProc, 
  10478.                                          myDisposeTokenProc,
  10479.                                          myGetMarkTokenProc, myMarkProc,
  10480.                                          myAdjustMarksProc,
  10481.                                          myGetErrDescProc: ProcPtr): OSErr;
  10482. myCompareProc
  10483. Either a pointer to the object-comparison function provided by your application or NIL if no function is provided.
  10484. myCountProc
  10485. Either a pointer to the object-counting function provided by your application or NIL if no function is provided.
  10486. myDisposeTokenProc
  10487. Either a pointer to the token disposal function provided by your application or NIL if no function is provided.
  10488. myGetMarkTokenProc
  10489. Either a pointer to the function for returning a mark token provided by your application or NIL if no function is provided.
  10490. myMarkProc    Either a pointer to the object-marking function provided by your application or NIL if no function is provided.
  10491. myAdjustMarksProc
  10492. Either a pointer to the mark-adjusting function provided by your application or NIL if no function is provided.
  10493. myGetErrDescProc
  10494. Either a pointer to the error callback function provided by your application or NIL if no function is provided.
  10495. DESCRIPTION
  10496. Your application can provide only one each of the object callback functions specified by AESetObjectCallbacks: one object-comparison function, one object-counting function, and so on. As a result, each of these callback functions must perform the requested task (comparing, counting, and so on) for all the object classes that your application supports. In contrast, your application may provide many different object accessor functions if necessary, depending on the object classes and token types your application supports.
  10497. To replace object callback routines that have been previously installed, you can make another call to AESetObjectCallbacks. Each additional call to AESetObjectCallbacks replaces any object callback functions installed by previous calls to AESetObjectCallbacks. You cannot use AESetObjectCallbacks to replace system object callback routines or object accessor functions. Only those routines you specify are replaced; to avoid replacing existing callback functions, specify a value of NIL for the functions you don’t want to replace.
  10498. RESULT CODESnoErr    0    No error occurred    
  10499. paramErr    –50    The handler pointer is NIL or odd, or AEObjectInit was not called before this function    
  10500. memFullErr    –108    There is not enough room in heap zone    
  10501. errAENotASpecialFunction    –1714    The keyword is not valid for a special function    
  10502.  
  10503. SEE ALSO
  10504. For information about writing object callback functions, see “Application-Defined Routines,” which begins on page 6-94.
  10505. To install system object callback functions, use the AEInstallSpecialHandler function described on page 4-100.  
  10506. Getting, Calling, and Removing Object Accessor Functions
  10507.  
  10508. The Apple Event Manager provides three functions that allow you to get, call, and remove object accessor functions that you have installed in either the system or application object accessor dispatch table with the AEInstallObjectAccessor function. The AEGetObjectAccessor and AECallObjectAccessor functions get and call object accessor functions installed in the dispatch table you specify, and AERemoveObjectAccessor removes an installed function.
  10509. AEGetObjectAccessor
  10510.  
  10511. You can use the AEGetObjectAccessor function to get a pointer to an object accessor function and the value of its reference constant. 
  10512. FUNCTION AEGetObjectAccessor (desiredClass: DescType; 
  10513.                                         containerType: DescType;
  10514.                                         VAR theAccessor: AccessorProcPtr;
  10515.                                         VAR accessorRefcon: LongInt; 
  10516.                                         isSysHandler: Boolean): OSErr;
  10517. desiredClass
  10518. The object class of the Apple event objects located by the requested object accessor function. This parameter can also contain the constant typeWildCard or the constant cProperty.
  10519. containerType
  10520. The descriptor type of the token that identifies the container for the objects located by the requested object accessor function. This parameter can also contain the constant typeWildCard.
  10521. theAccessor
  10522. The AEGetObjectAccessor function returns a pointer to the requested object accessor function in this parameter.
  10523. accessorRefcon
  10524. The AEGetObjectAccessor function returns the reference constant from the object accessor dispatch table entry for the specified object accessor function in this parameter.
  10525. isSysHandler
  10526. A value that specifies the object accessor table from which to get the object accessor function and its reference constant. If the value of isSysHandler is TRUE, AEGetObjectAccessor gets the function from the system object accessor dispatch table. If the value of isSysHandler is FALSE, AEGetObjectAccessor gets the function from the application’s object accessor dispatch table.
  10527. DESCRIPTION
  10528. The AEGetObjectAccessor function returns a pointer to the object accessor function installed for the object class specified in the desiredClass parameter and the descriptor type specified in the containerType parameter. It also returns the reference constant associated with the specified function. You must supply a value in the isSysHandler parameter that specifies which object accessor dispatch table you want to get the function from. 
  10529. Calling AEGetObjectAccessor does not remove the object accessor function from an object accessor dispatch table.
  10530. To get an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the object class, you must specify typeWildCard as the value of the desiredClass parameter. Similarly, to get an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the descriptor type of the token used to specify the container, you must specify typeWildCard as the value of the containerType parameter.
  10531. To get an object accessor function whose entry in an object accessor dispatch table specifies cProperty (a constant used to specify a property of any object class), you must specify cProperty as the desiredClass parameter. 
  10532. RESULT CODESnoErr    0    No error occurred    
  10533. paramErr    –50    AEObjectInit was not called before this function was called    
  10534. errAEAccessorNotFound    –1723    There is no object accessor function for the specified object class and container type      
  10535.  
  10536. AECallObjectAccessor
  10537.  
  10538. You can use the AECallObjectAccessor function to invoke one of your application’s object accessor functions. 
  10539. FUNCTION AECallObjectAccessor (desiredClass: DescType; 
  10540.                                          containerToken: AEDesc; 
  10541.                                          containerClass: DescType; 
  10542.                                          keyForm: DescType; 
  10543.                                          keyData: AEDesc; 
  10544.                                          VAR theToken: AEDesc): OSErr;
  10545. desiredClass
  10546. The object class of the desired Apple event objects.
  10547. containerToken
  10548. The token that identifies the container for the desired objects.
  10549. containerClass
  10550. The object class of the container for the desired objects.
  10551. keyForm    The key form specified by the object specifier record for the object or objects to be located.
  10552. keyData    The key data specified by the object specifier record for the object or objects to be located.
  10553. theToken    The object accessor function that is invoked returns a token specifying the desired object or objects in this parameter.
  10554. DESCRIPTION
  10555. If you want your application to do some of the Apple event object resolution normally performed by the AEResolve function, you can use AECallObjectAccessor to invoke an object accessor function. This might be useful, for example, if you have installed an object accessor function using typeWildCard for the AEInstallObjectAccessor function’s desiredClass parameter and typeAEList for the containerType parameter. To return a list of tokens for a request like “every line that ends in a period,” the object accessor function can create an empty list, then call AECallObjectAccessor for each requested element, adding tokens for each element to the list one at a time. 
  10556. The parameters of AECallObjectAccessor are identical to the parameters of an object accessor function, with one exception: the parameter that specifies the reference constant passed to the object accessor function whenever it is called is added by the Apple Event Manager when it calls the object accessor function.
  10557. To call an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the object class, you must specify typeWildCard as the value of the desiredClass parameter. 
  10558. To call an object accessor function whose entry in an object accessor dispatch table specifies cProperty, you must specify cProperty as the desiredClass parameter. 
  10559. RESULT CODES
  10560. In addition to the following result codes, AECallObjectAccessor returns any other result codes returned by the object accessor function that is called.noErr    0    No error occurred    
  10561. paramErr    –50    AEObjectInit was not called before this function was called    
  10562. errAEAccessorNotFound    –1723    No object accessor was found     
  10563.  
  10564. AERemoveObjectAccessor
  10565.  
  10566. You can use the AERemoveObjectAccessor function to remove an object accessor function from an object accessor dispatch table.  
  10567. FUNCTION AERemoveObjectAccessor (desiredClass: DescType; 
  10568.                                             containerType: DescType; 
  10569.                                             theAccessor: AccessorProcPtr; 
  10570.                                             isSysHandler: Boolean): OSErr;
  10571. desiredClass
  10572. The object class of the Apple event objects located by the object accessor function. The desiredClass parameter can also contain the constant typeWildCard or the constant cProperty.
  10573. containerType
  10574. The descriptor type of the token that identifies the container for the objects located by the object accessor function. The containerType parameter can also contain the constant typeWildCard.
  10575. theAccessor
  10576. A pointer to the object accessor function you want to remove. Although the parameters desiredClass and containerType would be sufficient to identify the function to be removed, providing the parameter theAccessor guarantees that you remove the correct function. If this parameter does not contain a pointer to the object accessor function you want to remove, its value should be NIL.
  10577. isSysHandler
  10578. A value that specifies the object accessor dispatch table from which to remove the object accessor function. If the value of isSysHandler is TRUE, AEGetObjectAccessor removes the routine from the system object accessor dispatch table. If the value is FALSE, AEGetObjectAccessor removes the routine from the application object accessor dispatch table.
  10579. DESCRIPTION
  10580. The AERemoveObjectAccessor function removes the object accessor function you have installed for the object class specified in the desiredClass parameter and the descriptor type specified in the containerType parameter. 
  10581. To remove an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the object class, you must specify typeWildCard as the value of the desiredClass parameter. Similarly, to remove an object accessor function whose entry in an object accessor dispatch table specifies typeWildCard as the descriptor type of the token used to specify the container for the desired objects, you must specify typeWildCard as the value of the containerType parameter.
  10582. To remove an object accessor function whose entry in an object accessor dispatch table specifies cProperty (a constant used to specify a property of any object class), you must specify cProperty as the desiredClass parameter. 
  10583. RESULT CODESnoErr    0    No error occurred    
  10584. paramErr    –50    AEObjectInit was not called before this function was called    
  10585. errAEAccessorNotFound    –1723    There is no object accessor function for the specified object class and container type      
  10586.  
  10587. Resolving Object Specifier Records
  10588.  
  10589. If an Apple event parameter consists of an object specifier record, your handler for the event typically calls the AEResolve function to begin the process of resolving the object specifier record. 
  10590. AEResolve
  10591.  
  10592. You can use the AEResolve function to resolve an object specifier record in an Apple event parameter.
  10593. FUNCTION AEResolve (objectSpecifier: AEDesc; 
  10594.                           callbackFlags: Integer; 
  10595.                           VAR theToken: AEDesc): OSErr;
  10596. objectSpecifier
  10597. The object specifier record to be resolved.
  10598. callbackFlags
  10599. A value that determines what additional assistance, if any, your application can give the Apple Event Manager when it parses the object specifier record. The value is specified by adding the following constants, as appropriate:
  10600.                 CONST            kAEIDoMinimum                    = $0000;                {supports minimum }
  10601.                                                                 { callbacks only}
  10602.                             kAEIDoWhose                    = $0001;                {supports formWhose}
  10603.                             kAEIDoMarking                    = $0004;                {provides marking }
  10604.                                                                 { functions} 
  10605. theToken    The AEResolve function returns, in this parameter, a token that identifies the Apple event objects specified by the objectSpecifier parameter. Your object accessor functions may need to create many tokens to resolve a single object specifier record; this parameter contains only the final token that identifies the requested Apple event object. If an error occurs, AEResolve returns a null descriptor record.
  10606. DESCRIPTION
  10607. The AEResolve function resolves the object specifier record passed in the objectSpecifier parameter with the help of the object accessor functions and object callback functions provided by your application. 
  10608. RESULT CODESnoErr    0    No error occurred    
  10609. paramErr    –50    AEObjectInit was not called before   this function was called    
  10610. errAEHandlerNotFound    –1717    The necessary object callback function was not found (this result is returned only for object callback functions; errAEAccessorNotFound [–1723] is returned when an object accessor function is not found)    
  10611. errAEImpossibleRange    –1720    The range is not valid because it is impossible for a range to include the first and last objects that were specified; an example is a range in which the offset of the first object is greater than the offset of the last object    
  10612. errAEWrongNumberArgs    –1721    The number of operands provided for the kAENOT logical operator is not 1    
  10613. errAEAccessorNotFound    –1723    There is no object accessor function for the specified object class and token descriptor type    
  10614. errAENoSuchLogical    –1725    The logical operator in a logical descriptor record is not kAEAND, kAEOR, or kAENOT    
  10615. errAEBadTestKey    –1726    The descriptor record in a test key is neither a comparison descriptor record nor a logical descriptor record    
  10616. errAENotAnObjectSpec    –1727    The objSpecifier parameter of AEResolve is not an object specifier record    
  10617. errAENegativeCount    –1729    An object-counting function returned a negative result    
  10618. errAEEmptyListContainer    –1730    The container for an Apple event object is specified by an empty list    
  10619.  
  10620. In addition to the result codes listed here, AEResolve also returns any result code returned by one of your application’s object accessor functions or object callback functions. For example, an object accessor function can return errAENoSuchObject (–1728) when it can’t find an Apple event object, or it can return more specific result codes.
  10621. If any object accessor function or object callback function returns a result code other than noErr or errAEEventNotHandled, AEResolve immediately disposes of any existing tokens and returns. The result code it returns in this case is the result code returned by the object accessor function or the object callback function. 
  10622. SEE ALSO
  10623. For an overview of the way AEResolve works with object accessor functions, see “Resolving Object Specifier Records,” which begins on page 6-4.
  10624. Deallocating Memory for Tokens
  10625.  
  10626. Whenever the AEResolve function returns a final token to your event handler as the result of the resolution of an object specifier record passed to AEResolve, your application can call the AEDisposeToken function to deallocate the memory used by the token. 
  10627. AEDisposeToken
  10628.  
  10629. You can use the AEDisposeToken function to deallocate the memory used by a token.
  10630. FUNCTION AEDisposeToken (VAR theToken: AEDesc): OSErr;
  10631. theToken    The token to be disposed of.
  10632. DESCRIPTION
  10633. When your application calls the AEDisposeToken function, the Apple Event Manager first calls your application’s token disposal function, if you have provided one. If you haven’t provided a token disposal function, or if your application’s token disposal function returns errAEEventNotHandled as the function result, the Apple Event Manager calls the system token disposal function if one is available. If there is no system token disposal function or the function returns errAEEventNotHandled as the function result, the Apple Event Manager calls the AEDisposeDesc function to dispose of the token.
  10634. RESULT CODES
  10635. In addition to the following result codes, AEDisposeToken also returns result codes returned by the token disposal function that disposed of the token.noErr    0    No error occurred    
  10636. paramErr    –50    AEObjectInit was not called before this function was called    
  10637. notASpecialFunction    –1714    The keyword is not valid for a special function    
  10638.  
  10639. SEE ALSO
  10640. For information about writing a token disposal function, see page 6-99. 
  10641. Creating Object Specifier Records
  10642.  
  10643. The Apple Event Manager provides five functions that you can use to create some of the components of an object specifier record or to assemble an object specifier record: 
  10644. n    The CreateOffsetDescriptor function creates an offset descriptor record, which specifies the position of an element in relation to the beginning or end of its container.
  10645. n    The CreateCompDescriptor function creates a comparison descriptor record, which specifies how to compare one or more Apple event objects with either another Apple event object or a descriptor record.
  10646. n    The CreateLogicalDescriptor function creates a logical descriptor record, which specifies a logical operator and one or more logical terms for the Apple Event Manager to evaluate.
  10647. n    The CreateRangeDescriptor function creates a range descriptor record, which specifies a series of consecutive elements in the same container.
  10648. n    The CreateObjSpecifier function assembles an object specifier record, which identifies one or more Apple event objects, from other descriptor records.
  10649. Instead of using these functions, you can create the corresponding descriptor records yourself using the AECreateDesc function, add them to an AE record using other Apple Event Manager routines, and coerce the AE record to a descriptor record of type typeObjectSpecifier. However, in most cases it is easier to use the functions listed in this section. 
  10650. All of these functions except for CreateOffsetDescriptor include a disposeInputs parameter. If the value of this parameter is TRUE, the function automatically disposes of any descriptor records you have provided as parameters to the function. If the value is FALSE, the application must dispose of the records itself. A value of FALSE may be more efficient for some applications because it allows them to reuse descriptor records.
  10651. For more information about these functions and examples of their use, see “Creating Object Specifier Records,” which begins on page 6-55.
  10652. CreateOffsetDescriptor
  10653.  
  10654. You can use the CreateOffsetDescriptor function to create an offset descriptor record. 
  10655. FUNCTION CreateOffsetDescriptor (theOffset: LongInt; 
  10656.                                             VAR theDescriptor: AEDesc) 
  10657.                                             : OSErr;
  10658. theOffset    A positive integer that specifies the offset from the beginning of the container (the first element has an offset of 1), or a negative integer that specifies the offset from the end (the last element has an offset of –1).
  10659. theDescriptor
  10660. The offset descriptor record created by CreateOffsetDescriptor.
  10661. DESCRIPTION
  10662. The CreateOffsetDescriptor function creates an offset descriptor record that specifies the position of an element in relation to the beginning or end of its container.
  10663. RESULT CODESnoErr    0    No error occurred    
  10664. memFullErr    –108    Not enough room in heap zone     
  10665.  
  10666. CreateCompDescriptor
  10667.  
  10668. You can use the CreateCompDescriptor function to create a comparison descriptor record.
  10669. FUNCTION CreateCompDescriptor (comparisonOperator: DescType;
  10670.                                          VAR operand1: AEDesc; 
  10671.                                          VAR operand2: AEDesc; 
  10672.                                          disposeInputs: Boolean; 
  10673.                                          VAR theDescriptor: AEDesc)
  10674.                                          : OSErr;
  10675. comparisonOperator
  10676. The comparison operator for comparing the descriptor records in the operand1 and operand2 parameters. The operator is specified by the constants listed in the description that follows.
  10677. operand1    An object specifier record.
  10678. operand2    A descriptor record (which can be an object specifier record or any other descriptor record) whose value is to be compared to the value of operand1.
  10679. disposeInputs
  10680. A Boolean value indicating whether the function (TRUE) or your application (FALSE) should dispose of the descriptor records for the two operands.
  10681. theDescriptor
  10682. The comparison descriptor record created by CreateCompDescriptor.
  10683. DESCRIPTION
  10684. The CreateCompDescriptor function creates a comparison descriptor record, which specifies how to compare one or more Apple event objects with either another Apple event object or a descriptor record.
  10685. The actual comparison of the two operands is performed by the object-comparison function provided by the client application. The way a comparison operator is interpreted is up to each application.
  10686. These are the currently defined standard comparison operators:
  10687. Constant    Meaning    
  10688. kAEGreaterThan    The value of operand1 is greater than the value of operand2.    
  10689. kAEGreaterThanEquals    The value of operand1 is greater than or equal to the value of operand2.    
  10690. kAEEquals    The value of operand1 is equal to the value of operand2.    
  10691. kAELessThan    The value of operand1 is less than the value of operand2.    
  10692. kAELessThanEquals    The value of operand1 is less than or equal to the value of operand2.    
  10693. kAEBeginsWith    The value of operand1 begins with the value of operand2 (for example, the string "operand" begins with the string "opera").    
  10694. kAEEndsWith    The value of operand1 ends with the value of operand2 (for example, the string "operand" ends with the string "and").    
  10695. kAEContains    The value of operand1 contains the value of operand2 (for example, the string "operand" contains the string "era").    
  10696.  
  10697. RESULT CODESnoErr    0    No error occurred    
  10698. paramErr    –50    Error in parameter list    
  10699. memFullErr    –108    Not enough room in heap zone    
  10700. errAECoercionFail     –1700    Data could not be coerced to the requested Apple event data type    
  10701. errAEWrongDataType    –1703    Wrong Apple event data type    
  10702. errAENotAEDesc    –1704    Not a valid descriptor record    
  10703. errAEBadListItem    –1705    Operation involving a list item failed    
  10704.  
  10705. SEE ALSO
  10706. For an example of how to use the CreateCompDescriptor function to create a comparison descriptor record, see “Specifying a Test,” which begins on page 6-64. 
  10707. CreateLogicalDescriptor
  10708.  
  10709. You can use the CreateLogicalDescriptor function to create a logical descriptor record. 
  10710. FUNCTION CreateLogicalDescriptor 
  10711.                                         (VAR theLogicalTerms: AEDescList; 
  10712.                                          theLogicOperator: DescType; 
  10713.                                          disposeInputs: Boolean; 
  10714.                                          VAR theDescriptor: AEDesc): OSErr;
  10715. theLogicalTerms
  10716. A list containing comparison descriptor records, logical descriptor records, or both. If the value of the parameter theLogicOperator is kAEAND or kAEOR, the list can contain any number of descriptors. If the value of the parameter theLogicOperator is kAENOT, logically this list should contain a single descriptor record. However, the function will not return an error if the list contains more than one descriptor record for a logical operator of kAENOT.
  10717. theLogicOperator
  10718. A logical operator represented by one of the following constants: 
  10719.                 CONST            kAEAND         = 'AND ';
  10720.                             kAEOR         = 'OR  ';
  10721.                             kAENOT         = 'NOT ';
  10722. disposeInputs
  10723. A Boolean value indicating whether the function (TRUE) or your application (FALSE) should dispose of the descriptor records in the other parameters.
  10724. theDescriptor
  10725. The logical descriptor record created by CreateLogicalDescriptor.
  10726. DESCRIPTION
  10727. The CreateLogicalDescriptor function creates a logical descriptor record, which specifies a logical operator and one or more logical terms for the Apple Event Manager to evaluate.
  10728. RESULT CODESnoErr    0    No error occurred    
  10729. paramErr    –50    Error in parameter list    
  10730. memFullErr    –108    Not enough room in heap zone    
  10731. errAECoercionFail    –1700    Data could not be coerced to requested Apple event data type    
  10732. errAEWrongDataType    –1703    Wrong Apple event data type    
  10733. errAENotAEDesc    –1704    Not a valid descriptor record    
  10734. errAEBadListItem    –1705    Operation involving a list item failed    
  10735.  
  10736. SEE ALSO
  10737. For an example of how to use the CreateLogicalDescriptor function to create a logical descriptor record, see “Specifying a Test,” which begins on page 6-64. 
  10738. CreateRangeDescriptor
  10739.  
  10740. You can use the CreateRangeDescriptor function to create a range descriptor record. 
  10741. FUNCTION CreateRangeDescriptor (VAR rangeStart: AEDesc; 
  10742.                                           VAR rangeStop: AEDesc; 
  10743.                                           disposeInputs: Boolean; 
  10744.                                           VAR theDescriptor: AEDesc): OSErr;
  10745. rangeStart
  10746. An object specifier record that identifies the first Apple event object in the range.
  10747. rangeStop    An object specifier record that identifies the last Apple event object in the range.
  10748. disposeInputs
  10749. A Boolean value indicating whether the function (TRUE) or your application (FALSE) should dispose of the descriptor records for the rangeStart and rangeStop parameters. 
  10750. theDescriptor
  10751. The range descriptor record created by CreateRangeDescriptor.
  10752. DESCRIPTION
  10753. The CreateRangeDescriptor function creates a range descriptor record, which specifies a series of consecutive elements in the same container. Although the rangeStart and rangeStop parameters can be any object specifier records—including object specifier records that specify more than one Apple event object—most applications expect these parameters to specify single Apple event objects.
  10754. RESULT CODESnoErr    0    No error occurred    
  10755. paramErr    –50    Error in parameter list    
  10756. memFullErr    –108    Not enough room in heap zone    
  10757. errAECoercionFail    –1700    Data could not be coerced to the requested Apple event data type    
  10758. errAEWrongDataType    –1703    Wrong Apple event data type    
  10759. errAENotAEDesc    –1704    Not a valid descriptor record    
  10760. errAEBadListItem    –1705    Operation involving a list item failed    
  10761.  
  10762. SEE ALSO
  10763. For an example of how to use the CreateRangeDescriptor function to create a range descriptor record, see “Specifying a Range” on page 6-72. 
  10764. CreateObjSpecifier
  10765.  
  10766. You can use the CreateObjSpecifier function to create an object specifier record.
  10767. FUNCTION CreateObjSpecifier (desiredClass: DescType; 
  10768.                                       VAR theContainer: AEDesc; 
  10769.                                       keyForm: DescType; 
  10770.                                       VAR keyData: AEDesc; 
  10771.                                       disposeInputs: Boolean; 
  10772.                                       VAR objSpecifier: AEDesc): OSErr;
  10773. desiredClass
  10774. The object class of the desired Apple event objects.
  10775. theContainer
  10776. A description of the container for the requested object, usually in the form of another object specifier record.
  10777. keyForm    The key form for the object specifier record.
  10778. keyData    The key data for the object specifier record.
  10779. disposeInputs
  10780. A Boolean value indicating whether the function (TRUE) or your application (FALSE) should dispose of the descriptor records for the other parameters.
  10781. objSpecifier
  10782. The object specifier record created by the CreateObjSpecifier function.
  10783. DESCRIPTION
  10784. The CreateObjSpecifier function assembles an object specifier record from the specified constants and other descriptor records.
  10785. RESULT CODESnoErr    0    No error occurred    
  10786. paramErr    –50    Error in parameter list    
  10787. memFullErr    –108    Not enough room in heap zone    
  10788. errAECoercionFail     –1700    Data could not be coerced to the requested Apple event data type    
  10789. errAEWrongDataType    –1703    Wrong Apple event data type    
  10790. errAENotAEDesc    –1704    Not a valid descriptor record    
  10791. errAEBadListItem    –1705    Operation involving a list item failed    
  10792.  
  10793. SEE ALSO
  10794. For information about how to assemble the components of an object specifier record with the CreateObjSpecifier function, see “Creating Object Specifier Records,” which begins on page 6-55.   
  10795. Application-Defined Routines
  10796.  
  10797. The AEResolve function performs tasks that are required to resolve any object specifier record, such as parsing its contents, keeping track of the results of tests, and handling memory management. When necessary, AEResolve calls application-defined functions to perform tasks that are unique to the application, such as locating a specific Apple event object in the application’s data structures or counting the number of Apple event objects in a container. 
  10798. AEResolve can call two kinds of application-defined functions:
  10799. n    Object accessor functions locate Apple event objects. Every application that supports simple object specifier records must provide one or more object accessor functions. 
  10800. n    Object callback functions perform other tasks that only an application can perform, such as counting, comparing, or marking Apple event objects. You can provide up to seven object callback functions, depending on the needs of your application.
  10801. This section provides model declarations for the object accessor functions and object callback functions that your application can provide.
  10802. Object Accessor Functions
  10803.  
  10804. You must provide one or more object accessor functions that can locate all the element classes and properties listed in the Apple Event Registry: Standard Suites for the object classes supported by your application. This section provides the routine declaration for an object accessor function.
  10805. MyObjectAccessor
  10806.  
  10807. Object accessor functions locate Apple event objects of a specified object class in a container identified by a token of a specified descriptor type. 
  10808. FUNCTION MyObjectAccessor (desiredClass: DescType; 
  10809.                                     containerToken: AEDesc; 
  10810.                                     containerClass: DescType; 
  10811.                                     keyForm: DescType; keyData: AEDesc; 
  10812.                                     VAR theToken: AEDesc; 
  10813.                                     theRefcon: LongInt): OSErr;
  10814. desiredClass
  10815. The object class of the desired Apple event objects.
  10816. containerToken
  10817. A token that specifies the container of the desired Apple event objects.
  10818. containerClass
  10819. The object class of the container.
  10820. keyForm    The key form specified by the object specifier record being resolved.
  10821. keyData    The key data specified by the object specifier record being resolved.
  10822. theToken    The token returned by the MyObjectAccessor function.
  10823. theRefcon    A reference constant that the Apple Event Manager passes to the object accessor function each time it is called.
  10824. DESCRIPTION
  10825. Each object accessor function provided by your application should either find elements of a specified object class or find properties of an Apple event object. The AEResolve function uses the object class ID of the specified Apple event object and the descriptor type of the token that identifies the object’s container to determine which object accessor function to call. To install an object accessor function either in your application’s object accessor dispatch table or in the system object accessor dispatch table, use the AEInstallObjectAccessor function, which is described on page 6-78. 
  10826. SPECIAL CONSIDERATIONS
  10827. If the Apple Event Manager receives the result code errAEEventNotHandled after calling an object accessor function, it attempts to use other methods of locating the requested objects, such as calling an equivalent system object accessor function. Thus, an object accessor function that can’t locate a requested object should return errAEEventNotHandled. This allows the Apple Event Manager to try other object accessor functions that may be available.
  10828. RESULT CODESnoErr    0    No error occurred    
  10829. errAEEventNotHandled    –1708    The object accessor function is unable to locate the requested Apple event object or objects    
  10830.  
  10831. SEE ALSO
  10832. For information about installing object accessor functions, see “Installing Entries in the Object Accessor Dispatch Tables,” which begins on page 6-21.
  10833. For information about writing object accessor functions, see “Writing Object Accessor Functions,” which begins on page 6-28. 
  10834. Object Callback Functions
  10835.  
  10836. If an Apple event parameter consists of an object specifier record, your handler for the Apple event typically calls AEResolve to begin the process of locating the requested Apple event objects. The AEResolve function in turn calls object accessor functions and, if necessary, object callback functions provided by your application when it needs the information they can provide.
  10837. This section provides declarations for the seven object callback functions that your application can provide: the object-counting function (MyCountObjects), object-comparison function (MyCompareObjects), token disposal function (MyDisposeToken), error callback function (MyGetErrorDesc), mark token function (MyGetMarkToken), object-marking function (MyMark), and mark-adjusting function (MyAdjustMarks).
  10838. For information about writing and installing object callback functions, see “Writing Object Callback Functions,” which begins on page 6-45. 
  10839. MyCountObjects
  10840.  
  10841. If you want the Apple Event Manager to help your application resolve object specifier records of key form formTest (and if your application doesn’t specify kAEIDoWhose as described on page 6-48), you should provide an object-counting function and an object-comparison function. An object-counting function counts the number of Apple event objects of a specified class in a specified container. 
  10842. FUNCTION MyCountObjects (desiredClass: DescType; 
  10843.                                  containerClass: DescType; 
  10844.                                  theContainer: AEDesc; 
  10845.                                  VAR result: LongInt): OSErr;
  10846. desiredClass
  10847. The object class of the Apple event objects to be counted.
  10848. containerClass
  10849. The object class of the container for the Apple event objects to be counted.
  10850. theContainer
  10851. A token that identifies the container for the Apple event objects to be counted.
  10852. result    Your object-counting function should return in this parameter the number of Apple objects of the specified class in the specified container.
  10853. DESCRIPTION
  10854. The Apple Event Manager calls your object-counting function when, in the course of resolving an object specifier record, the manager requires a count of the number of Apple event objects of a given class in a given container. 
  10855. SPECIAL CONSIDERATIONS
  10856. If the Apple Event Manager receives the result code errAEEventNotHandled after calling an object-counting function, it attempts to use other methods of counting the specified objects, such as calling an equivalent system object-counting function. Thus, an object-counting function that can’t count the specified objects should return errAEEventNotHandled. This allows the Apple Event Manager to try other object-counting functions that may be available.
  10857. RESULT CODESnoErr    0    No error occurred    
  10858. errAEEventNotHandled    –1708    The object-counting function is unable to count the specified Apple event objects    
  10859.  
  10860. SEE ALSO
  10861. For more information, see “Writing an Object-Counting Function” on page 6-48. 
  10862. MyCompareObjects
  10863.  
  10864. If you want the Apple Event Manager to help your application resolve object specifier records of key form formTest (and if your application doesn’t specify kAEIDoWhose as described on page 6-48), you should provide an object-counting function and an object-comparison function. After comparing one Apple event object to another or to the data for a descriptor record, an object-comparison function should return TRUE or FALSE in the result parameter. 
  10865. FUNCTION MyCompareObjects (comparisonOperator: DescType; 
  10866.                                     object: AEDesc; 
  10867.                                     objectOrDescToCompare: AEDesc; 
  10868.                                     VAR result: Boolean): OSErr;
  10869. comparisonOperator
  10870. The comparison operator. See the description of CreateCompDescriptor on page 6-89 for standard comparison operators at the time of publication of this book. The current version of the Apple Event Registry: Standard Suites lists all the constants for comparison operators.
  10871. object    A token.
  10872. objectOrDescToCompare
  10873. A token or some other descriptor record that specifies either an Apple event object or a value to compare to the Apple event object specified by the object parameter.
  10874. result    Your object-comparison function should return, in this parameter, a Boolean value that indicates whether the values of the object and objectOrDescToCompare parameters have the relationship specified by the comparisonOperator parameter (TRUE) or not (FALSE).
  10875. DESCRIPTION
  10876. The Apple Event Manager calls your object-comparison function when, in the course of resolving an object specifier record, the manager needs to compare an Apple event object with another or with a value.
  10877. It is up to your application to interpret the comparison operators it receives. The meaning of comparison operators differs according to the Apple event objects being compared, and not all comparison operators apply to all object classes. 
  10878. SPECIAL CONSIDERATIONS
  10879. If the Apple Event Manager receives the result code errAEEventNotHandled after calling an object-comparison function, it attempts to use other methods of comparison, such as calling an equivalent system object-comparison function. Thus, an object-comparison function that can’t perform a requested comparison should return errAEEventNotHandled. This allows the Apple Event Manager to try other object-comparison functions that may be available.
  10880. RESULT CODESnoErr    0    No error occurred    
  10881. errAEEventNotHandled    –1708    The object-comparison function is unable to compare the specified Apple event objects    
  10882.  
  10883. SEE ALSO
  10884. For more information, see “Writing an Object-Comparison Function” on page 6-50.
  10885. MyDisposeToken
  10886.  
  10887. If your application requires more than a call to the AEDisposeDesc function to dispose of a token, or if it supports marking callback functions, you must provide one token disposal function. A token disposal function disposes of a specified token. 
  10888. FUNCTION MyDisposeToken (VAR unneededToken: AEDesc): OSErr;
  10889. unneededToken
  10890. The token to dispose of.
  10891. DESCRIPTION
  10892. The Apple Event Manager calls your token disposal function whenever it needs to dispose of a token. It also calls your disposal function when your application calls the AEDisposeToken function. If your application does not provide a token disposal function, the Apple Event Manager calls AEDisposeDesc instead.
  10893. Your token disposal function must be able to dispose of all of the token types used by your application. 
  10894. If your application supports marking, a call to MyDisposeToken to dispose of a mark token lets your application know that it can unmark the objects marked with that mark token. 
  10895. SPECIAL CONSIDERATIONS
  10896. If the Apple Event Manager receives the result code errAEEventNotHandled after calling a token disposal function, it attempts to dispose of the token by some other method, such as calling an equivalent system token disposal function if one is available or, if that fails, by calling AEDisposeDesc. Thus, a token disposal function that can’t dispose of a token should return errAEEventNotHandled. This allows the Apple Event Manager to try other token disposal functions that may be available.
  10897. RESULT CODESnoErr    0    No error occurred    
  10898. errAEEventNotHandled    –1708    The token disposal function is unable to dispose of the token    
  10899.  
  10900. MyGetErrorDesc
  10901.  
  10902. If you want to find out which descriptor record is responsible for an error that occurs during a call to the AEResolve function, you can provide an error callback function. An error callback function returns a pointer to an address. The Apple Event Manager uses this address to store the descriptor record it is currently working with if an error occurs during a call to AEResolve.
  10903. FUNCTION MyGetErrorDesc (VAR errDescPtr: DescPtr): OSErr;
  10904. errDescPtr
  10905. A pointer to an address.
  10906. DESCRIPTION
  10907. Your error callback function simply returns an address. Shortly after your application calls AEResolve, the Apple Event Manager calls your error callback function and writes a null descriptor record to the address returned, overwriting whatever was there previously. If an error occurs during the resolution of the object specifier record, the Apple Event Manager calls your error callback function again and writes the descriptor record—often an object specifier record—to the address returned. If AEResolve returns an error during the resolution of an object specifier record, this address contains the descriptor record responsible for the error.
  10908. Normally you should maintain a single global variable of type AEDesc whose address your error callback function returns no matter how many times it is called. Be careful if you use any other method. When recovering from an error, the Apple Event Manager never writes to the address you provide unless it already contains a null descriptor record. Thus, if you don’t maintain a single global variable as just described, you should write null descriptor records to any addresses passed by your error callback function that are different from the addresses returned the first time your function is called after a given call to AEResolve.
  10909. If the result code returned by the MyGetErrorDesc function has a nonzero value, the Apple Event Manager continues to resolve the object specifier record as if it had never called the error callback function.
  10910. RESULT CODEnoErr    0    No error occurred     
  10911.  
  10912. MyGetMarkToken
  10913.  
  10914. If your application supports marking, you must provide one mark token function. A mark token function returns a mark token. 
  10915. FUNCTION MyGetMarkToken (containerToken: AEDesc; 
  10916.                                  containerClass: DescType; 
  10917.                                  VAR result: AEDesc): OSErr;
  10918. containerToken
  10919. The Apple event object that contains the elements to be marked with the mark token.
  10920. containerClass
  10921. The object class of the container that contains the objects to be marked.
  10922. result    Your mark token function should return a mark token in this parameter.
  10923. DESCRIPTION
  10924. To get a mark token, the Apple Event Manager calls your mark token function. Like other tokens, the mark token returned can be a descriptor record of any type; however, unlike other tokens, a mark token identifies the way your application will mark Apple event objects during the current session while resolving a single object specifier record that specifies the key form formTest. 
  10925. A mark token is valid until the Apple Event Manager either disposes of it (by calling AEDisposeToken) or returns it as the result of the AEResolve function. If the final result of a call to AEResolve is a mark token, the Apple event objects currently marked for that mark token are those specified by the object specifier record passed to AEResolve, and your application can proceed to do whatever the Apple event has requested. Note that your application is responsible for disposing of a final mark token with a call to AEDisposeToken, just as for any other final token.
  10926. If your application supports marking, it should also provide a token disposal function modeled after the token disposal function described on page 6-99. When the Apple Event Manager calls AEDisposeToken to dispose of a mark token that is not the final result of a call to AEResolve, the subsequent call to your token disposal function lets you know that you can unmark the Apple event objects marked with that mark token. A call to AEDisposeDesc to dispose of a mark token (which would occur if you did not provide a token disposal function) would go unnoticed. 
  10927. RESULT CODESnoErr    0    No error occurred    
  10928. errAEEventNotHandled    –1708    The mark token function is unable to return a mark token; if the Apple Event Manager gets this result, it attempts to get a mark token by calling the equivalent system marking callback function    
  10929.  
  10930. SEE ALSO
  10931. For more information, see “Writing Marking Callback Functions,” which begins on page 6-53. 
  10932. MyMark
  10933.  
  10934. If your application supports marking, you must provide one object-marking function. An object-marking function marks a specific Apple event object. 
  10935. FUNCTION MyMark (theToken: AEDesc; markToken: AEDesc; 
  10936.                       markCount: LongInt): OSErr;
  10937. theToken    The token for the Apple event object to be marked.
  10938. markToken    The mark token used to mark the Apple event object.
  10939. markCount    The number of times MyMark has been called for the current mark token (that is, the number of Apple event objects that have so far passed the test, including the element to be marked).
  10940. DESCRIPTION
  10941. To mark an Apple event object using the current mark token, the Apple Event Manager calls the object-marking function provided by your application. In addition to marking the specified object, your MyMark function should record the mark count for each object that it marks. The mark count recorded for each marked object allows your application to determine which of a set of marked tokens pass a test, as described in the next section for the MyAdjustMarks function.
  10942. RESULT CODESnoErr    0    No error occurred    
  10943. errAEEventNotHandled    –1708    The MyMark function is unable to mark the specified Apple event object; if the Apple Event Manager gets this result, it attempts to mark the object by calling the equivalent system object-marking function    
  10944.  
  10945. SEE ALSO
  10946. For more information, see “Writing Marking Callback Functions,” which begins on page 6-53.
  10947. MyAdjustMarks
  10948.  
  10949. If your application supports marking, you must provide one mark-adjusting function. A mark-adjusting function adjusts the marks made with the current mark token. 
  10950. FUNCTION MyAdjustMarks (newStart, newStop: LongInt; 
  10951.                                 markToken: AEDesc): OSErr;
  10952. newStart    The mark count value (provided when the MyMark callback routine was called to mark the object) for the first object in the new set of marked objects.
  10953. newStop    The mark count value (provided when the MyMark callback routine was called to mark the object) for the last object in the new set of marked objects.
  10954. markToken    The mark token for the marked objects.
  10955. DESCRIPTION
  10956. When the Apple Event Manager needs to identify either a range of elements or the absolute position of an element in a group of Apple event objects that pass a test, it can use your application’s mark-adjusting function to unmark objects previously marked by a call to your marking function. For example, suppose an object specifier record specifies “any row in the table ‘MyCustomers’ for which the City column is ‘San Francisco.’” The Apple Event Manager first uses the appropriate object accessor function to locate all the rows in the table for which the City column is “San Francisco” and calls the application’s marking function repeatedly to mark them. It then generates a random number between 1 and the number of rows it found that passed the test and calls the application’s mark-adjusting function to unmark all the rows whose mark count does not match the randomly generated number. If the randomly chosen row has a mark count value of 5, the Apple Event Manager passes the value 5 to the mark-adjusting function in both the newStart parameter and the newStop parameter, and passes the current mark token in the markToken parameter. 
  10957. When the Apple Event Manager calls your MyAdjustMarks function, your application must dispose of any data structures that it created to mark the previously marked objects.
  10958. RESULT CODESnoErr    0    No error occurred    
  10959. errAEEventNotHandled    –1708    The MyAdjustMarks function is unable to adjust the marks as requested; if the Apple Event Manager gets this result, it attempts to adjust the marks by calling the equivalent system mark-adjusting function    
  10960.  
  10961. SEE ALSO
  10962. For more information, see “Writing Marking Callback Functions” on page 6-53.  
  10963.  
  10964.  
  10965. Summary of Resolving and Creating Object Specifier Records
  10966.  
  10967. Pascal Summary
  10968.  
  10969. Constants
  10970.  
  10971. CONST        
  10972.     gestaltAppleEventsAttr                                    = 'evnt';                {selector for Apple events}
  10973.     gestaltAppleEventsPresent                                    = 0;                {if this bit is set, Apple }
  10974.                                                         { Event Manager is available}
  10975.  
  10976.     {logical operators for descriptor records with keyword } 
  10977.     { keyAELogicalOperator}
  10978.     kAEAND                                =    'AND ';                
  10979.     kAEOR                                =    'OR  ';
  10980.     kAENOT                                =    'NOT ';
  10981.  
  10982.     {absolute ordinals used as key data in an object specifier } 
  10983.     { record with key form formAbsolutePosition}
  10984.     kAEFirst                                =    'firs';
  10985.     kAELast                                =    'last';
  10986.     kAEMiddle                                =    'midd';
  10987.     kAEAny                                =    'any ';
  10988.     kAEAll                                =    'all ';
  10989.  
  10990.     {relative ordinals used as key data in an object specifier record }
  10991.     { with key form formRelativePosition}
  10992.     kAENext                                =    'next';
  10993.     kAEPrevious                                =    'prev';
  10994.     
  10995.     {keywords for object specifier records} 
  10996.     keyAEDesiredClass                                =    'want'; {object class ID}
  10997.     keyAEContainer                                =    'from'; {description of container}
  10998.     keyAEKeyForm                                =    'form'; {key form}
  10999.     keyAEKeyData                                 =     'seld'; {key data for specified key form}
  11000.  
  11001.     {keywords for range descriptor records}
  11002.     keyAERangeStart                                =    'star';                {beginning of range}
  11003.     keyAERangeStop                                =    'stop';                {end of range}
  11004.     
  11005.     {values for the keyAEKeyForm field of an object specifier record}                         
  11006.     formAbsolutePosition                                 =    'indx'        ;        {for example, 1 = first }
  11007.                                                         { element in container, -2 = }
  11008.                                                         { second from end of container}
  11009.     formRelativePosition                                =    'rele';                {key data specifies element }
  11010.                                                         { before or after container}
  11011.     formTest                                =    'test';                {key data specifies a test}
  11012.     formRange                                =    'rang';                {key data specifies a range}
  11013.     formPropertyID                                =    'prop';                {key data is property ID}
  11014.     formName                                =    'name';                {key data is element's name}
  11015.  
  11016.     {descriptor types used to identify Apple event objects}
  11017.     typeObjectSpecifier                                 =     'obj ';                {object specifier record, often }
  11018.                                                         { used as keyAEContainer}
  11019.     typeObjectBeingExamined =                                  'exmn';                    {used as keyAEContainer}
  11020.     typeCurrentContainer                                =    'ccnt';                {used as keyAEContainer}
  11021.     typeToken                                =    'toke';                {substituted for 'ccnt' }
  11022.                                                         { before accessor called}
  11023.     typeAbsoluteOrdinal                                 =    'abso';                {formAbsolutePosition}
  11024.     typeRangeDescriptor                                 =     'rang';                {formRange}
  11025.     typeLogicalDescriptor                                =     'logi';                {formTest}
  11026.     typeCompDescriptor                                =    'cmpd';                {formTest}
  11027.  
  11028.     {various relevant keywords}
  11029.     keyAECompOperator                                =    'relo';                {operator for comparison: }
  11030.                                                         { '=', '<=', etc.}
  11031.     keyAELogicalTerms                                =    'term';                {an AEList of terms to be }
  11032.                                                         { related by 'logc' below}
  11033.     keyAELogicalOperator                                =    'logc';                {kAEAND, kAEOR, or kAENOT}
  11034.     keyAEObject1                                =    'obj1';                {first of two objects being }
  11035.                                                         { compared; must be object }
  11036.                                                         { specifier record}
  11037.     keyAEObject2                                =    'obj2';                {the other object; may be }
  11038.                                                         { simple descriptor record }
  11039.                                                         { or object specifier record}
  11040.  
  11041.     {special handler selectors used with AESetObjectCallbacks}
  11042.     keyDisposeTokenProc                                =    'xtok';
  11043.     keyAECompareProc                                 =     'cmpr';
  11044.     keyAECountProc                                 =     'cont';
  11045.     keyAEMarkTokenProc                                 =     'mkid';
  11046.     keyAEMarkProc                                 =     'mark';
  11047.     keyAEAdjustMarksProc                                 =     'adjm';
  11048.     keyAEGetErrDescProc                                 =     'indc';
  11049.  
  11050.     {additive values for callbackFlags parameter to AEResolve}
  11051.     kAEIDoMinimum                                =    $0000;            {server does not support whose }
  11052.                                                     { descriptor records or marking}
  11053.     kAEIDoWhose                                =    $0001;            {server supports whose }
  11054.                                                     { descriptor records}
  11055.     kAEIDoMarking                                =    $0004;            {server supports marking}
  11056.  
  11057.     {constants for whose descriptor records}
  11058.     typeWhoseDescriptor                                =    'whos';            {whose descriptor record}
  11059.     formWhose                                =    'whos';            {key form for key data of descriptor }
  11060.                                                     { type typeWhoseDescriptor}
  11061.     typeWhoseRange                                =    'wrng';             {whose range descriptor record}
  11062.     keyAEWhoseRangeStart                                =    'wstr';            {beginning of range}
  11063.     keyAEWhoseRangeStop                                =    'wstp';            {end of range}
  11064.     keyAEIndex                                =    'kidx';            {index for whose descriptor record}
  11065.     keyAETest                                =    'ktst';            {test for whose descriptor record}
  11066. Data Types
  11067.  
  11068. TYPE
  11069.     ccntTokenRecord =                                                     {used for rewriting tokens in }
  11070.     RECORD                                                    { place of 'ccnt' descriptor }
  11071.         tokenClass:                     DescType;                            { records; only of interest to }
  11072.         token:                     AEDesc;                            { those who, when they get ranges }
  11073.     END;                                                    { as key data in their object }
  11074.                                                         { accessor functions, resolve }
  11075.     ccntTokenRecPtr = ^ccntTokenRecord;                                                    { the object specifier records }
  11076.     ccntTokenRecHandle = ^ccntTokenRecPtr;                                                    { for the end points manually}
  11077.  
  11078.     DescPtr = ^AEDesc;
  11079.     DescHandle = ^DescPtr;
  11080.  
  11081.     AccessorProcPtr = ProcPtr;
  11082. Routines for Resolving and Creating Object Specifier Records
  11083.  
  11084. Initializing the Object Support Library
  11085. FUNCTION AEObjectInit : OSErr;
  11086. Setting Object Accessor Functions and Object Callback Functions
  11087. FUNCTION AEInstallObjectAccessor
  11088. (desiredClass: DescType; 
  11089. containerType: DescType; 
  11090. theAccessor: AccessorProcPtr; 
  11091. accessorRefcon: LongInt; 
  11092. isSysHandler: Boolean): OSErr;
  11093. FUNCTION AESetObjectCallbacks
  11094. (myCompareProc, myCountProc, 
  11095. myDisposeTokenProc,                                        
  11096. myGetMarkTokenProc, myMarkProc,
  11097. myAdjustMarksProc, myGetErrDescProc: 
  11098. ProcPtr): OSErr;
  11099. Getting, Calling, and Removing Object Accessor Functions
  11100. FUNCTION AEGetObjectAccessor
  11101. (desiredClass: DescType; 
  11102. containerType: DescType;
  11103. VAR theAccessor: AccessorProcPtr;
  11104. VAR accessorRefcon: LongInt; 
  11105. isSysHandler: Boolean): OSErr;
  11106. FUNCTION AECallObjectAccessor
  11107. (desiredClass: DescType; 
  11108. containerToken: AEDesc;
  11109. containerClass: DescType; 
  11110. keyForm: DescType; 
  11111. keyData: AEDesc; 
  11112. VAR theToken: AEDesc): OSErr;
  11113. FUNCTION AERemoveObjectAccessor
  11114. (desiredClass: DescType; 
  11115. containerType: DescType; 
  11116. theAccessor: AccessorProcPtr; 
  11117. isSysHandler: Boolean): OSErr;
  11118. Resolving Object Specifier Records
  11119. FUNCTION AEResolve     (objectSpecifier: AEDesc; 
  11120. callbackFlags: Integer;
  11121. VAR theToken: AEDesc): OSErr;
  11122. Deallocating Memory for Tokens
  11123. FUNCTION AEDisposeToken     (VAR theToken: AEDesc): OSErr;
  11124. Creating Object Specifier Records
  11125. FUNCTION CreateOffsetDescriptor
  11126. (theOffset: LongInt; 
  11127. VAR theDescriptor: AEDesc): 
  11128. OSErr;
  11129. FUNCTION CreateCompDescriptor
  11130. (comparisonOperator: DescType;
  11131. VAR operand1: AEDesc; 
  11132. VAR operand2: AEDesc; 
  11133. disposeInputs: Boolean; 
  11134. VAR theDescriptor: AEDesc): OSErr;
  11135. FUNCTION CreateLogicalDescriptor
  11136. (VAR theLogicalTerms: AEDescList; 
  11137. theLogicOperator: DescType; 
  11138. disposeInputs: Boolean; 
  11139. VAR theDescriptor: AEDesc): OSErr;
  11140. FUNCTION CreateRangeDescriptor
  11141. (VAR rangeStart: AEDesc; 
  11142. VAR rangeStop: AEDesc; 
  11143. disposeInputs: Boolean; 
  11144. VAR theDescriptor: AEDesc): OSErr;
  11145. FUNCTION CreateObjSpecifier    (desiredClass: DescType;
  11146. VAR theContainer: AEDesc; 
  11147. keyForm: DescType; 
  11148. VAR keyData: AEDesc; 
  11149. disposeInputs: Boolean; 
  11150. VAR objSpecifier: AEDesc): OSErr;
  11151. Application-Defined Routines
  11152.  
  11153. Object Accessor Functions
  11154. FUNCTION MyObjectAccessor     (desiredClass: DescType; 
  11155. containerToken: AEDesc; 
  11156. containerClass: DescType; 
  11157. keyForm: DescType; keyData: AEDesc; 
  11158. VAR theToken: AEDesc; 
  11159. theRefcon: LongInt): OSErr;
  11160. Object Callback Functions
  11161. FUNCTION MyCountObjects    (desiredClass: DescType; 
  11162. containerClass: DescType; 
  11163. theContainer: AEDesc; 
  11164. VAR result: LongInt): OSErr;
  11165. FUNCTION MyCompareObjects    (comparisonOperator: DescType; 
  11166. theobject: AEDesc; 
  11167. objectOrDescToCompare: AEDesc; 
  11168. VAR result: Boolean): OSErr;
  11169. FUNCTION MyDisposeToken     (VAR unneededToken: AEDesc): OSErr;
  11170. FUNCTION MyGetErrorDesc     (VAR errDescPtr: DescPtr): OSErr;
  11171. FUNCTION MyGetMarkToken     (containerToken: AEDesc; 
  11172. containerClass: DescType; 
  11173. VAR result: AEDesc): OSErr;
  11174. FUNCTION MyMark     (theToken: AEDesc; markToken: AEDesc;
  11175. markCount: LongInt): OSErr;
  11176. FUNCTION MyAdjustMarks     (newStart, newStop: LongInt; 
  11177. markToken: AEDesc): OSErr;
  11178. C Summary
  11179.  
  11180. Constants
  11181.  
  11182. enum {
  11183.         #define         gestaltAppleEventsAttr                                      'evnt'            /*selector for Apple events*/
  11184.         gestaltAppleEventsPresent                                             = 0        /*if this bit is set, then */
  11185.                                                             /* Apple Event Manager is */
  11186. };                                                            /* available*/
  11187.  
  11188. /*logical operators for descriptor records with keyword */ 
  11189. /* keyAELogicalOperator*/
  11190. #define kAEAND                                                'AND '                
  11191. #define kAEOR                                                'OR  '
  11192. #define kAENOT                                                'NOT '
  11193.  
  11194. /*absolute ordinals used as key data in an object specifier */ 
  11195. /* record with key form formAbsolutePosition*/
  11196. #define kAEFirst                                                'firs'
  11197. #define kAELast                                                'last'
  11198. #define kAEMiddle                                                'midd'
  11199. #define kAEAny                                                'any '
  11200. #define kAEAll                                                'all '
  11201.  
  11202. /*relative ordinals used as key data in an object specifier record */
  11203. /* with key form formRelativePosition*/
  11204. #define kAENext                                                'next'
  11205. #define kAEPrevious                                                'prev'
  11206.  
  11207. /*keywords for object specifier records*/                                                             
  11208. #define keyAEDesiredClass                                                'want'            /*object class ID*/
  11209. #define keyAEContainer                                                'from'            /*description of container*/
  11210. #define keyAEKeyForm                                                'form'            /*key form*/
  11211. #define keyAEKeyData                                                  'seld'            /*key data for specified key */
  11212.                                                             /* form*/
  11213.  
  11214. /*keywords for range descriptor records*/
  11215. #define keyAERangeStart                                                'star'            /*beginning of range*/
  11216. #define keyAERangeStop                                                'stop'            /*end of range*/
  11217.     
  11218. /*values for the keyAEKeyForm field of an object specifier record*/                         
  11219. #define formAbsolutePosition                                                 'indx'             /*for example, 1 = first */
  11220.                                                             /* element in container, -2 = */
  11221.                                                             /* second from end of */
  11222.                                                             /* container*/
  11223. #define formRelativePosition                                                'rele'             /*key data specifies element */
  11224.                                                             /* before or after container*/
  11225. #define formTest                                                'test'            /*key data specifies a test*/
  11226. #define formRange                                                'rang'             /*key data specifies a range*/
  11227. #define formPropertyID                                                'prop'             /*key data is property ID*/
  11228. #define formName                                                'name'             /*key data is element's name*/
  11229.  
  11230. /* descriptor types used to identify Apple event objects*/
  11231. #define typeObjectSpecifier                                                  'obj '            /*object specifier record, */
  11232.                                                             /* often used as */
  11233.                                                             /* keyAEContainer*/
  11234. #define typeObjectBeingExamined                                                 'exmn'            /*used as keyAEContainer*/
  11235. #define typeCurrentContainer                                                'ccnt'            /*used as keyAEContainer*/
  11236. #define typeToken                                                'toke'            /*substituted for 'ccnt' */
  11237.                                                             /* before accessor called*/
  11238. #define typeAbsoluteOrdinal                                                 'abso'            /*formAbsolutePosition*/
  11239. #define typeRangeDescriptor                                                  'rang'            /*formRange*/
  11240. #define typeLogicalDescriptor                                                 'logi'            /*formTest*/
  11241. #define typeCompDescriptor                                                'cmpd'            /*formTest*/
  11242. /*various relevant keywords*/
  11243. #define keyAECompOperator                                                'relo'            /*operator for comparison: */
  11244.                                                             /* '=', '<=', etc.*/
  11245. #define keyAELogicalTerms                                                'term'            /*an AEList of terms to be */
  11246.                                                             /* related by 'logc' below*/
  11247. #define keyAELogicalOperator                                                'logc'            /*kAEAND, kAEOR, or kAENOT*/
  11248. #define keyAEObject1                                                'obj1'            /*first of two objects being */
  11249.                                                             /* compared; must be object */
  11250.                                                             /* specifier record*/
  11251. #define keyAEObject2                                                'obj2'            /*the other object; may be */
  11252.                                                             /* simple descriptor record */
  11253.                                                             /* or object specifier record*/
  11254. /*special handler selectors used with AESetObjectCallbacks*/
  11255. #define keyDisposeTokenProc                                                'xtok'
  11256. #define keyAECompareProc                                                  'cmpr'
  11257. #define keyAECountProc                                                  'cont'
  11258. #define keyAEMarkTokenProc                                                  'mkid'
  11259. #define keyAEMarkProc                                                  'mark'
  11260. #define keyAEAdjustMarksProc                                                  'adjm'
  11261. #define keyAEGetErrDescProc                                                  'indc'
  11262.  
  11263. /*additive values for callbackFlags parameter to AEResolve*/
  11264. #define kAEIDoMinimum                                                0x0000            /*server does not support */
  11265.                                                             /* whose descriptor records */
  11266.                                                             /* or marking*/
  11267. #define kAEIDoWhose                                                0x0001            /*server supports whose */
  11268.                                                             /* descriptor records*/
  11269. #define kAEIDoMarking                                                0x0004            /*server supports marking*/
  11270.  
  11271. /*constants for whose descriptor records*/
  11272. #define typeWhoseDescriptor                                                'whos'            /*whose descriptor record*/
  11273. #define formWhose                                                'whos'            /*key form for key data of */
  11274.                                                             /* descriptor type */
  11275.                                                             /* typeWhoseDescriptor*/
  11276. #define typeWhoseRange                                                'wrng'            /*whose range descriptor */
  11277.                                                             /* record*/
  11278. #define keyAEWhoseRangeStart                                                'wstr'            /*beginning of range*/
  11279. #define keyAEWhoseRangeStop                                                'wstp'            /*end of range*/
  11280. #define keyAEIndex                                                'kidx'            /*index for whose descriptor */
  11281.                                                             /* record*/
  11282. #define keyAETest                                                'ktst'            /*test for whose descriptor */
  11283.                                                             /* record*/
  11284. Data Types
  11285.  
  11286. struct ccntTokenRecord                             {                                /*used for rewriting tokens */
  11287.     DescType tokenClass                        ;                                /* in place of 'ccnt' */
  11288.     AEDesc token                ;                                        /* descriptor records; only */
  11289. };                                                            /* of interest to those who, */
  11290.                                                             /* when they get ranges as */
  11291. typedef struct ccntTokenRecord ccntTokenRecord,                                                             /* key data in their object */
  11292. *ccntTokenRecPtr, **ccntTokenRecHandle;                                                            /* accessor functions, */ 
  11293.                                                             /* resolve them manually*/
  11294.  
  11295. typedef AEDesc *DescPtr, **DescHandle;
  11296.  
  11297. /*typedefs providing type checking for procedure pointers*/
  11298. typedef pascal OSErr (*accessorProcPtr) (DescType desiredClass,
  11299.                                                         const AEDesc *container, 
  11300.                                                         DescType containerClass, 
  11301.                                                         DescType form,
  11302.                                                         const AEDesc *selectionData, 
  11303.                                                         AEDesc *value, long LongInt);
  11304. typedef pascal OSErr (*compareProcPtr)(DescType oper, const AEDesc *obj1,
  11305.                                                     const AEDesc *obj2,
  11306.                                                     Boolean *result);
  11307. typedef pascal OSErr (*countProcPtr)(DescType desiredClass, 
  11308.                                                     DescType containerClass,
  11309.                                                     const AEDesc *container, 
  11310.                                                     long *result);
  11311. typedef pascal OSErr (*disposeTokenProcPtr)(AEDesc *unneededToken);
  11312. typedef pascal OSErr (*getMarkTokenProcPtr)(const AEDesc *ContainerToken, 
  11313.                                                             DescType containerClass,
  11314.                                                             AEDesc *result);
  11315.  
  11316. typedef pascal OSErr (*getErrDescProcPtr)(DescPtr *appDescPtr);
  11317. Routines for Resolving and Creating Object Specifier Records
  11318.  
  11319. Initializing the Object Support Library
  11320. pascal OSErr AEObjectInit    ();
  11321. Setting Object Accessor Functions and Object Callback Functions
  11322. pascal OSErr AEInstallObjectAccessor
  11323. (DescType desiredClass, DescType containerType,
  11324. accessorProcPtr theAccessor,
  11325. long accessorRefcon, Boolean isSysHandler);
  11326. pascal OSErr AESetObjectCallbacks
  11327. (compareProcPtr myCompareProc, 
  11328. countProcPtr myCountProc, 
  11329. disposeTokenProcPtr myDisposeTokenProc, 
  11330. getMarkTokenProcPtr myGetMarkTokenProc, markProcPtr myMarkProc, 
  11331. adjustMarksProcPtr myAdjustMarksProc, getErrDescProcPtr myGetErrDescProc);
  11332. Getting, Calling, and Removing Object Accessor Functions
  11333. pascal OSErr AEGetObjectAccessor
  11334. (DescType desiredClass, DescType containerType,
  11335. accessorProcPtr *theAccessor,
  11336. long *accessorRefcon, Boolean isSysHandler);
  11337. pascal OSErr AECallObjectAccessor
  11338. (DescType desiredClass, 
  11339. const AEDesc *containerToken, 
  11340. DescType containerClass, DescType keyForm, 
  11341. const AEDesc *keyData, AEDesc *theToken);
  11342. pascal OSErr AERemoveObjectAccessor
  11343. (DescType desiredClass, DescType containerType,
  11344. accessorProcPtr theAccessor, 
  11345. Boolean isSysHandler);
  11346. Resolving Object Specifier Records
  11347. pascal OSErr AEResolve    (const AEDesc *objectSpecifier, 
  11348. short callbackFlags, AEDesc *theToken);
  11349. Deallocating Memory for Tokens
  11350. pascal OSErr AEDisposeToken    (AEDesc *theToken);
  11351. Creating Object Specifier Records
  11352. pascal OSErr CreateOffsetDescriptor
  11353. (long theOffset, AEDesc *theDescriptor);
  11354. pascal OSErr CreateCompDescriptor
  11355. (DescType comparisonOperator, AEDesc* operand1,
  11356. AEDesc* operand2, Boolean                                             disposeInputs, 
  11357. AEDesc* theDescriptor);
  11358. pascal OSErr CreateLogicalDescriptor
  11359. (AEDescList *theLogicalTerms, 
  11360. DescType theLogicOperator, 
  11361. Boolean disposeInputs, AEDesc *theDescriptor);
  11362. pascal OSErr CreateRangeDescriptor
  11363. (AEDesc *rangeStart, AEDesc *rangeStop,
  11364. Boolean disposeInputs, AEDesc *theDescriptor);
  11365. pascal OSErr CreateObjSpecifier
  11366. (DescType desiredClass, AEDesc *theContainer,
  11367. DescType                                         keyForm, AEDesc *keyData, 
  11368. Boolean disposeInputs, AEDesc *objSpecifier);
  11369. Application-Defined Routines
  11370.  
  11371. Object Accessor Functions
  11372. pascal OSErr MyObjectAccessor
  11373. (DescType desiredClass, 
  11374. const AEDesc *containerToken, 
  11375. DescType containerClass, 
  11376. DescType keyForm, const AEDesc *keyData, 
  11377. AEDesc *theToken, long *theRefcon);
  11378. Object Callback Functions
  11379. pascal OSErr MyCountObjects    (DescType desiredClass, DescType containerClass, 
  11380. const AEDesc *theContainer, long *result);
  11381. pascal OSErr MyCompareObjects
  11382. (DescType comparisonOperator, 
  11383. const AEDesc *theObject, 
  11384. const AEDesc *objectOrDescToCompare, 
  11385. Boolean *result);
  11386. pascal OSErr MyDisposeToken    (AEDesc *unneededToken);
  11387. pascal OSErr MyGetErrorDesc    (DescPtr *errDescPtr);
  11388. pascal OSErr MyGetMarkToken    (const AEDesc *containerToken, 
  11389. DescType containerClass, AEDesc *result);
  11390. pascal OSErr MyMark    (const AEDesc *theToken, 
  11391. const AEDesc *markToken, long markCount);
  11392. pascal OSErr MyAdjustMarks    (long newStart, long newStop, 
  11393. const AEDesc *markToken);
  11394. Assembly-Language Summary
  11395.  
  11396. Trap Macros
  11397.  
  11398. Trap Macros Requiring Routine Selectors
  11399. _Pack8
  11400. Selector    Routine    
  11401. $023A    AEDisposeToken    
  11402. $0536    AEResolve    
  11403. $0738    AERemoveObjectAccessor    
  11404. $0937    AEInstallObjectAccessor    
  11405. $0939    AEGetObjectAccessor    
  11406. $0C3B    AECallObjectAccessor    
  11407. $0E35    AESetObjectCallbacks    
  11408.  
  11409. Result CodesnoErr    0    No error    
  11410. paramErr    –50    Parameter error (for example, value of handler pointer is NIL or odd)    
  11411. eLenErr    –92    Buffer too big to send    
  11412. memFullErr    –108    Not enough room in heap zone    
  11413. userCanceledErr    –128    User canceled an operation    
  11414. procNotFound    –600    No eligible process with specified process serial number    
  11415. bufferIsSmall    –607    Buffer is too small    
  11416. noOutstandingHLE    –608    No outstanding high-level event    
  11417. connectionInvalid    –609    Nonexistent signature or session ID    
  11418. noUserInteractionAllowed    –610    Background application sends event requiring authentication    
  11419. noPortErr    –903    Client hasn’t set 'SIZE' resource to indicate awareness of high-level events    
  11420. destPortErr    –906    Server hasn’t set 'SIZE' resource to indicate awareness of high-level events, or else is not present    
  11421. sessClosedErr    –917    The kAEDontReconnect flag in the sendMode parameter was set, and the server quit and then restarted    
  11422. errAECoercionFail    –1700    Data could not be coerced to the requested descriptor type    
  11423. errAEDescNotFound    –1701    Descriptor record was not found    
  11424. errAECorruptData    –1702    Data in an Apple event could not be read    
  11425. errAEWrongDataType    –1703    Wrong descriptor type    
  11426. errAENotAEDesc    –1704    Not a valid descriptor record    
  11427. errAEBadListItem    –1705    Operation involving a list item failed    
  11428. errAENewerVersion    –1706    Need a newer version of the Apple Event Manager    
  11429. errAENotAppleEvent    –1707    Event is not an Apple event    
  11430. errAEEventNotHandled    –1708    Event wasn’t handled by an Apple event handler    
  11431. errAEReplyNotValid    –1709    AEResetTimer was passed an invalid reply    
  11432. errAEUnknownSendMode    –1710    Invalid sending mode was passed    
  11433. errAEWaitCanceled    –1711    User canceled out of wait loop for reply or receipt    
  11434. errAETimeout    –1712    Apple event timed out    
  11435. errAENoUserInteraction    –1713    No user interaction allowed    
  11436. errAENotASpecialFunction    –1714    The keyword is not valid for a special function    
  11437. errAEParamMissed    –1715    Handler cannot understand a parameter the client considers required    
  11438. errAEUnknownAddressType    –1716    Unknown Apple event address type    
  11439. errAEHandlerNotFound    –1717    No handler found for an Apple event or a coercion, or no object callback function found    
  11440. errAEReplyNotArrived    –1718    Reply has not yet arrived    
  11441. errAEIllegalIndex    –1719    Not a valid list index    
  11442. errAEImpossibleRange    –1720    The range is not valid because it is impossible for a range to include the first and last objects that were specified; an example is a range in which the offset of the first object is greater than the offset of the last object    
  11443. errAEWrongNumberArgs    –1721    The number of operands provided for the kAENOT logical operator is not 1    
  11444. errAEAccessorNotFound    –1723    There is no object accessor function for the specified object class and token descriptor type    
  11445. errAENoSuchLogical    –1725    The logical operator in a logical descriptor record is not kAEAND, kAEOR, or kAENOT    
  11446. errAEBadTestKey    –1726    The descriptor record in a test key is neither a comparison descriptor record nor a logical descriptor record    
  11447. errAENotAnObjectSpec    –1727    The objSpecifier parameter of AEResolve is not an object specifier record    
  11448. errAENoSuchObject    –1728     A run-time resolution error, for example: object specifier record asked for the third element, but there are only 2.    
  11449. errAENegativeCount    –1729     Object-counting function returned negative value    
  11450. errAEEmptyListContainer    –1730    The container for an Apple event object is specified by an empty list    
  11451. errAEUnknownObjectType    –1731    Descriptor type of token returned by AEResolve is not known to server application     
  11452. errAERecordingIsAlreadyOn    –1732    Attempt to turn recording on when it is already on    
  11453.  
  11454.  
  11455.  
  11456. Listing 7-0
  11457. Table 7-0
  11458. Introduction to Scripting
  11459. Contents
  11460. About Scripts and Scripting Components7-4
  11461. Script Editors and Script Files7-6
  11462. Scripting Components and Scriptable Applications7-8
  11463. Scripting Components and Applications That Execute Scripts7-11
  11464. Making Your Application Scriptable7-14
  11465. About Apple Event Terminology Resources7-15
  11466. How AppleScript Uses Terminology Information7-17
  11467. Dynamic Loading of Terminology Information7-20
  11468. Making Your Application Recordable7-20
  11469. Manipulating and Executing Scripts7-22
  11470. Compiling, Saving, Modifying, and Executing Scripts7-24
  11471. Using a Script Context to Handle an Apple Event7-25
  11472. Introduction to Scripting
  11473. This chapter provides an overview of the tasks involved in making your application scriptable and recordable. This chapter also introduces some of the ways your application can use the Component Manager and scripting components to manipulate and execute scripts. The three chapters that follow provide detailed information, including sample code, about the topics introduced in this chapter.
  11474. The chapter “Introduction to Interapplication Communication” in this book describes the Open Scripting Architecture (OSA) and its relationship to the Apple Event Manager and other parts of the IAC architecture. If your application supports the appropriate core and functional-area events defined in the Apple Event Registry: Standard Suites, you can make it scriptable (that is, capable of responding to Apple events sent by scripting components) by providing an Apple event terminology extension ('aete') resource. This chapter describes some of the tasks involved in making your application scriptable and introduces the 'aete' resource. The next chapter, “Apple Event Terminology Resources,” describes in detail how to create an 'aete' resource.
  11475. This chapter also introduces Apple event recording and the use of the standard scripting component routines to manipulate and execute scripts. The chapter “Recording Apple Events” describes in detail how to make your application recordable, and the chapter “Scripting Components” describes how to use the standard scripting component routines.
  11476. To use this chapter or any of the chapters that follow, you should be familiar with the chapters “Introduction to Apple Events” and “Responding to Apple Events” in this book. If you plan to make your application recordable, you should also read the chapters “Creating and Sending Apple Events” and “Resolving and Creating Object Specifier Records.”
  11477. The AppleScript Software Developers’ Kit (available from APDA) provides development tools, sample applications, and information about the AppleScript language that you will find useful when you begin to apply the information in this chapter to your application. 
  11478. If you are developing a scripting component, you should provide support for the standard scripting component routines described in the chapter “Scripting Components,” and you should read the instructions for creating components in the chapter “Component Manager” in Inside Macintosh: More Macintosh Toolbox. 
  11479. This chapter begins with an overview of scripts and scripting components. The rest of the chapter describes how the OSA makes it possible to 
  11480. n    make your application scriptable
  11481. n    make your application recordable
  11482. n    have your application manipulate and execute scripts
  11483.  
  11484.  
  11485. About Scripts and Scripting Components
  11486.  
  11487. A script is any collection of data that, when executed by the appropriate program, causes a corresponding action or series of actions. The Open Scripting Architecture (OSA) provides a standard mechanism that allows users to control multiple applications with scripts written in a variety of scripting languages. Each scripting language has a corresponding scripting component. Each scripting component supports the standard scripting component routines described in the chapter “Scripting Components” in this book.  
  11488. When a scripting component executes a script, it performs the actions described in the script, including sending Apple events to applications if necessary. Like other components that use the Component Manager, scripting components can provide their own routines in addition to the standard routines that must be supported by all components of the same type.
  11489. Scripting components typically implement a text-based scripting language based on Apple events. For example, the AppleScript component implements AppleScript, the standard user scripting language defined by Apple Computer, Inc. This book uses AppleScript examples to demonstrate how applications can interact with scripting components.  
  11490. Other scripting components may support the standard scripting component routines in different ways. Scripting components need not implement a text-based scripting language, or even one that is based on Apple events. For example, specialized scripting components can play sounds, execute XCMDs, or perform almost any other action when they execute scripts. 
  11491. This chapter describes three ways that you can take advantage of the OSA:
  11492. n    You can make your application scriptable, or capable of responding to Apple events sent to it by a scripting component. An application is scriptable if it
  11493. n    Responds to the appropriate standard Apple events as described in the chapter “Responding to Apple Events” in this book.
  11494. n    Provides an Apple event terminology extension ('aete') resource describing the Apple events that your application supports and the user terminology that corresponds to those events. The 'aete' resource allows scripting components to interpret scripts correctly and send the appropriate Apple events to your application during script execution.
  11495. n    You can make your application recordable—that is, capable of sending Apple events to itself to report user actions to the Apple Event Manager for recording purposes. After a user has turned on recording for a particular scripting component, the scripting component receives a copy of every subsequent Apple event that any application on the local computer sends to itself. The scripting component records such events in the form of a script. 
  11496. n    You can have your application manipulate and execute scripts with the aid of a scripting component. To do so, your application must
  11497. n    Use the Component Manager to open a connection with the appropriate component.
  11498. n    Use the standard scripting component routines described in the chapter “Scripting Components” to record, edit, compile, save, load, or execute scripts.
  11499. Users of scriptable applications can execute scripts to perform tasks that might otherwise be difficult to accomplish, especially repetitive or conditional tasks that involve multiple applications. For example, a user can execute an AppleScript script to locate database records with specific characteristics, create a series of graphs based on those records, import the graphs into a page-layout document, and send the document to a remote computer on the network via electronic mail. When a user executes such a script, the AppleScript component attempts to perform the actions the script describes, including sending Apple events when necessary. 
  11500. To respond appropriately to the Apple events sent to it by the AppleScript component, the database application in this example must be able to locate records with specific characteristics so that it can identify and return the requested data. These characteristics are described by an object specifier record that is part of an Apple event supported by the application. Also, the other applications involved must support Apple events that manipulate the data in the ways described in the script. Each application in this example must also provide an 'aete' resource describing the Apple events that the application supports and the user terminology that corresponds to those events, so that the AppleScript component can interpret the script correctly.
  11501. Even with little or no knowledge of a particular scripting language, users of applications that are recordable as well as scriptable can record simple scripts. More knowledgeable users may also wish to record their actions as scripts with recordable applications and then edit or combine scripts as needed.
  11502. An application that uses scripting components to manipulate and execute scripts need not be scriptable; however, if it is scriptable, it can execute scripts that control its own behavior. In other words, it can perform tasks by means of scripts and allow users to modify those scripts to suit their own needs.
  11503. The next three sections provide an overview of the way scripting components can interact with applications.
  11504. Script Editors and Script Files
  11505.  
  11506. A script editor is an application that allows users to record, edit, save, and execute scripts. For example, the AppleScript component uses the services of the Script Editor application.  
  11507. Figure 7-1 shows an AppleScript script displayed in a Script Editor window. The Record, Stop, and Run buttons control a script in much the same way that the equivalent buttons on a cassette recorder control an audio tape. A script comment at the top of the window describes what the script does. Users with some knowledge of a text-based scripting language such as AppleScript can use Script Editor to modify recorded scripts or write their own scripts.
  11508. Figure 7-1    A script window in the Script Editor application
  11509.  
  11510. Script Editor provides entry-level scripting capabilities, but it is not intended for intensive script development. Users who wish to write complex scripts may replace Script Editor with more sophisticated editors that provide specialized debugging and development tools.  
  11511. A script like the one in Figure 7-1 can be stored in a script file represented by an icon in the Finder, or it can be stored within an application or one of its documents. Figure 7-2 shows the four icons representing the files in which Script Editor stores scripts.
  11512. Figure 7-2    Script file icons in the Finder and corresponding user actions
  11513.  
  11514. Script Editor and similar script-editing applications allow users to store scripts using three file types:
  11515. n    A compiled script file has the file type 'osas' and contains the script data as a resource of type 'scpt'. Before executing the script in a compiled script file, a user must first open the script from the Finder or from an application such as Script Editor. After opening a compiled script in an application that supports script editing, the user can view the script, modify it if necessary, and execute it.
  11516. n    A script application has the file type 'APPL' and contains the script data as a resource of type 'scpt'. Its kind is “application.” A script application takes one of two forms, each with its own icon:  
  11517. n    A script application with the creator signature 'aplt'. A user double-clicks the icon to trigger the script.   
  11518. n    A script application with the creator signature 'dplt'. A user can drag the icon for another file or a folder over this script application’s icon to trigger a script that acts on that object.   
  11519. By default, when a user triggers the script in either kind of script application, a splash screen appears that allows the user either to quit or to run the script. Users can also save a script application in a form that bypasses the splash screen, running the script immediately after the user double-clicks its icon.
  11520. n    A script text file contains only a plain-text version of uncompiled scripting-language statements. This format is useful primarily as a last resort for saving a script that can’t be compiled because of syntax errors or other problems. It is also useful for exchanging unstyled text with other text-based applications. A user must open a script text file in a script editor and successfully compile it before it will execute. 
  11521. Like sound resources, scripts can be stored within applications and documents as well as in distinct files that can be manipulated from the Finder. Your application can use the standard scripting component routines to manipulate and execute both its own internally stored scripts and scripts stored as separate files whose icons appear in the Finder. For more information about script storage formats, see “Saving Script Data” on page 10-12. 
  11522. The next two sections describe how scripting components interact with scriptable applications and with applications that execute scripts.
  11523. Scripting Components and Scriptable Applications
  11524.  
  11525. Scripting components control the behavior of scriptable applications by means of Apple events. For example, when the AppleScript component executes the AppleScript script shown in Figure 7-1, it sends the Apple events shown in Figure 7-3 to trigger the actions described by the script. The client application in this example would most commonly be a script editor but could also be any other application that uses standard scripting component routines to manipulate and execute scripts. 
  11526. Figure 7-3    How the AppleScript component executes a script
  11527.  
  11528. As described in the chapter “Introduction to Apple Events” in this book, a client application is any application that uses Apple events to request a service or information. A client application that executes a script does not send the corresponding Apple events itself; instead, it uses scripting component routines to manipulate and execute the script. The scripting component sends Apple events when necessary to trigger the actions described in the script. Similarly, a scriptable application that responds to the Apple events sent by a scripting component can be considered the server application for those Apple events. 
  11529. When a scripting component evaluates a script, it attempts to perform all the actions described in the script, including sending Apple events when necessary. In the example shown in Figure 7-3, the AppleScript component first performs the action described in the first tell statement: 
  11530. tell application "SurfWriter"
  11531.     copy table "Summary of Sales" of document¬ 
  11532.         "Sales Report" to Totals
  11533. end tell
  11534. To perform this action, the AppleScript component sends a Get Data event to the SurfWriter application requesting the data from the specified table. The SurfWriter application returns the data to the AppleScript component in a standard reply Apple event, and the AppleScript component sets the value of the variable Totals to the data returned by SurfWriter.
  11535. Then the AppleScript component performs the action described in the second tell statement:
  11536. tell application "SurfCharter"
  11537.     copy Totals to Chart 1 of document "Sales Chart"
  11538. end tell
  11539. In this case, the AppleScript component sends a Set Data event to the SurfCharter application that sets the specified chart to the value of the variable Totals. 
  11540. Both SurfWriter and SurfCharter are server applications for the Apple events sent by the AppleScript component, because they are performing services in response to requests made by the client application via the script.
  11541. To send the appropriate Apple events to a scriptable application while executing a script, a scripting component must obtain information about the nature of that application’s support for Apple events and the human-language terminology to associate with those events. A scriptable application provides this information in the form of an Apple event terminology extension ('aete') resource. A scripting component uses both the 'aete' resource provided by a scriptable application and the Apple event user terminology ('aeut') resource provided by the scripting component itself to obtain the information it needs to execute a script that controls that application. 
  11542. See “Making Your Application Scriptable,” which begins on page 7-14, for an overview of the tasks you should perform to make your application scriptable and a more detailed description of the 'aete' and 'aeut' resources. See “Making Your Application Recordable” on page 7-20 for an overview of the tasks you should perform if you want your application to be recordable as well as scriptable.
  11543. Scripting Components and Applications That Execute Scripts
  11544.  
  11545. To store and execute scripts as a client application, your application must first establish a connection with a scripting component registered with the Component Manager on the same computer. Each scripting component can manipulate and execute scripts written in the corresponding scripting language when your application calls the standard scripting component routines.
  11546. Your application can use scripting component routines to
  11547. n    obtain a handle to a script in a form that can be saved, and load the script again when necessary
  11548. n    allow users to modify scripts that have been previously saved
  11549. n    compile and execute scripts
  11550. n    redirect Apple events to script contexts
  11551. n    supply application-defined functions for use by scripting components
  11552. n    control the recording process directly, turning recording off and on and saving the recorded script for use by your application
  11553. Your application can perform these tasks as a client application regardless of whether it is scriptable or recordable. If your application is scriptable, however, it can execute scripts that control its own behavior, thus acting as both the client application and the server application for the corresponding Apple events. For example, your application can allow users to associate a script with a custom menu command that performs a series of routine actions on a selected object, sets preferences, or automates other actions within your application.
  11554. You can also use scripting component routines to execute scripts that perform tasks for your application with the aid of other applications. For example, a user of a word-processing application might be able to attach a script to a specific word so that the application executes the script whenever that word is double-clicked. Such a script could trigger Apple events that cause other applications to look up and display related information, run a QuickTime movie, perform a calculation, play a voice annotation, and so on. 
  11555. Your application can associate a script with either Apple event objects or application-defined objects. Almost any user action can be used to trigger such a script: choosing a menu command, clicking a button, tabbing from one table cell to another, and so on. The script can be executed directly by the application when it detects a triggering action; or, if the script is associated with an Apple event object in the form of a script context, it can be executed automatically when a specified Apple event performs an action on that object.
  11556. The rest of this section describes one way that an application could execute such a script. Suppose a forms application allows users to create custom forms that can include scripts associated with specific fields on the form. These scripts are executed when the user presses Enter or Tab in the appropriate field. For the purposes of this example, it doesn’t matter whether a field with which a script is associated is an Apple event object (which can be described in an object specifier record) or some other application-defined object (which can’t be described in an object specifier record). 
  11557. A company could use the forms application to create a custom order form for taking telephone orders. If the customer has ordered from the company before, the user can quickly retrieve the customer’s address from the company database by typing the customer’s name in a field and pressing the Tab key. In response, the application executes the script associated with the field. The script might look like this in AppleScript:
  11558. set custName to field "Customer Name"
  11559.  
  11560. tell application SurfDB
  11561.     copy the first record in the table MyAddresses ¬
  11562.         whose cell "Customer Name" = custName to Address
  11563. end tell
  11564.  
  11565. set field "Street" to item 2 of Address
  11566. set field "City" to item 3 of Address
  11567. set field "Zip" to item 4 of Address
  11568. To execute such a script (or to manipulate it any other way, such as when the form is first created), the forms application must previously have established a connection with the appropriate scripting component—in this case, the AppleScript component. When the user enters a customer name and presses Tab, the forms application calls scripting component routines to execute the script. As shown in Figure 7-4, the AppleScript component first sends the forms application a Get Data event that requests the contents of the “Customer Name” field and sets the variable custName to that value. It then sends SurfDB a Get Data event that requests the appropriate address information and copies it to the variable Address. (The replies to the Get Data events are not shown in Figure 7-4.) Finally, the AppleScript component sends the forms application a Set Data event that copies the address information from the variable Address to the appropriate fields. 
  11569. The AppleScript component needs to maintain the binding of the variables custName and Address throughout execution of the script. Scripting components bind variables with the aid of a script context, which is a script that maintains context information for the execution of other scripts. An application specifies a script context when it executes a script. The forms application in Figure 7-4 provides a context for the scripting component to use whenever it executes a script associated with a button. 
  11570. Figure 7-4    How an application uses the AppleScript component to execute a script
  11571.  
  11572. In the example shown in Figure 7-4, the application executes the script directly when the cursor is in the appropriate field and the user presses Tab or Enter. Your application can also associate such a script with an object in the form of a script context, so that the script context is executed whenever a specified Apple event acts on the field. The section “Using a Script Context to Handle an Apple Event,” which begins on page 7-25, describes this approach in more detail. 
  11573. See “Manipulating and Executing Scripts,” which begins on page 7-22, for an overview of methods your application can use to save and load script data, compile source data, and perform other useful tasks with scripting component routines. The chapter “Scripting Components” in this book provides full implementation details, including sample code and human interface guidelines for associating scripts with objects. 
  11574.  
  11575. Making Your Application Scriptable
  11576.  
  11577. To make your application scriptable, you need to 
  11578. n    define a hierarchy of Apple event objects within your application that you want client applications to be able to identify—that is, which objects can be contained by other Apple event objects in your application, which properties each kind of object can have, and so on
  11579. n    write Apple event handlers, object accessor functions, and other routines required to implement the Apple events and related object classes that you want to support
  11580. n    create an 'aete' resource
  11581. The chapters “Introduction to Apple Events,” “Responding to Apple Events,” and “Resolving and Creating Object Specifier Records” in this book describe how to perform the first two tasks. The extent to which scripts can control your application depends mainly on the extent of your application’s support for Apple events. For example, if your application does not provide the Apple event handlers and object accessor functions required to locate and manipulate windows, users will not be able to use scripts to control your application’s windows. Although you should use the definitions in the Apple Event Registry: Standard Suites whenever possible, you have considerable freedom to extend or limit your implementation of the standard Apple events according to the needs of your application.
  11582. The OSA makes it possible to design new kinds of applications that always operate in the background and can be controlled only by means of scripts. For example, it is possible to design a simple telecommunications program that can log on to a network, send and receive text files created by another application, and perform other basic operations in response to scripts without providing any other form of user interface. Such an application would not need to support Apple events that control window movement, the File menu, or the Edit menu; instead, it would need to support only those Apple events that execute its basic telecommunications operations.
  11583. At the other extreme, some applications allow users to arrange windows, palettes, and dialog boxes on their screen in many different ways, or to customize menus or other aspects of the presentation of information. If such an application can respond to scripts that control windows, dialog boxes, specialized preferences, and other aspects of the presentation of information, it can allow users who might not otherwise explore those capabilities to take advantage of them. For example, a naive user could execute a script that sets up a powerful word processor with the appropriate menus, window and palette arrangement, and formatting templates for a particular task, such as producing a company newsletter.
  11584. Scripting components use 'aeut' and 'aete' resources to associate Apple event codes supported by your application with corresponding human-language terms used in scripts that control your application. Each scripting component supplies an 'aeut' resource, and each scriptable application provides an 'aete' resource. The next section introduces the 'aeut' and 'aete' resources. 
  11585. About Apple Event Terminology Resources
  11586.  
  11587. As explained in the chapter “Introduction to Apple Events” in this book, applications can support different combinations of the standard suites of Apple events. Applications can also extend the definitions of individual Apple events and object classes, or define custom Apple events and object classes. Scripting components use the Apple event user terminology resources, 'aeut' and 'aete', to associate the IDs, keywords, and other codes used in Apple events with the corresponding human-language terms used in scripts that control your application.  
  11588. The Apple event user terminology ('aeut') resource contains terminology information for all the standard suites of Apple events defined in the Apple Event Registry: Standard Suites. The resource consists of a sequence of concatenated arrays that map human-language names to each of the following:
  11589. n    the ID defined for each suite
  11590. n    the Apple events defined for each suite
  11591. n    the parameters defined for each Apple event
  11592. n    the Apple event object classes defined for each suite
  11593. n    the properties defined for each object class
  11594. n    the elements defined for each object class
  11595. n    the key forms defined for each element class
  11596. n    the comparison operators defined for each suite
  11597. n    the values for enumerators defined for each suite
  11598. Each scripting component provides its own 'aeut' resource. A scripting component can also provide different versions of the 'aeut' resource; for example, the user terminology provided by the 'aeut' resource for the AppleScript Japanese dialect component is in Japanese. The IDs, keywords, and other codes listed in the 'aeut' resource are based on the Apple Event Registry: Standard Suites and do not vary from one version to another.
  11599. An 'aete' resource has the same format as the 'aeut' resource but serves a different purpose. Each scriptable application must include its own 'aete' resource describing which of the standard suites listed in the 'aeut' resource it supports and providing other application-specific information. Since the human-language equivalents for the standard suites are defined in the 'aeut' resource, applications that support standard suites without any modifications do not have to define such equivalents; instead, they can simply list, in the 'aete' resource, the suites they support. The scripting component associates the standard suites listed in the 'aete' resource with the corresponding Apple event descriptions in its 'aeut' resource. 
  11600. Applications can also use the 'aete' resource to describe extensions to the standard suites, such as additional parameters for standard Apple events, additional properties and element classes for the standard Apple event object classes, and additional key forms for each element class. Information about such extensions must be included in the appropriate arrays of the 'aete' resource, along with the equivalent human-language terms. Similarly, an application can use the 'aete' resource to describe the parts of each standard suite it supports (if it doesn’t support the entire suite) and any custom Apple events or Apple event object classes defined by the application. 
  11601. The human language in which your Apple event extensions or custom Apple events are displayed in scripts depends on the corresponding user terminology you specify in your application’s 'aete' resource. Therefore, if your application implements such extensions or custom Apple events, you must provide a separate version of this resource for each localized version of your application.
  11602. Scripting components can use the information in the 'aete' and 'aeut' resources in a variety of ways. The next section, “How AppleScript Uses Terminology Information,” describes how the AppleScript component uses these resources when it executes or records a script. The next chapter, “Apple Event Terminology Resources,” describes how to create an 'aete' resource for your application.
  11603. If you want users to be able to control your application with scripts written in the AppleScript scripting language, you also need to know how the AppleScript component interprets AppleScript commands that trigger Apple events. In this way, you can make sure you support Apple events and specify the user terminology for your 'aete' resource in a way that translates easily into AppleScript statements. The section “Defining Terminology for Use by the AppleScript Component,” which begins on page 8-3, discusses these issues. If you implement Apple events so that they translate into logical and useful AppleScript scripts, your implementation will probably work well with other scripting components that resemble AppleScript. 
  11604. How AppleScript Uses Terminology Information
  11605.  
  11606. The manner in which the AppleScript component uses the information in 'aete' resources depends on specific characteristics of the AppleScript scripting language. An AppleScript expression consists of an internal compiled form and corresponding expressions in dialects, or versions of the AppleScript scripting language that resemble different human languages. Users can select the dialect they want to use from within the Script Editor application. If a script is displayed in a window and the user selects a different dialect, the AppleScript component converts the script to the new dialect. Users can install additional dialects as necessary.
  11607. This section describes how the AppleScript component uses the information in the 'aeut' and 'aete' resources, not how it obtains that information. For a description of the methods available to scripting components for loading information from terminology resources, see “Dynamic Loading of Terminology Information” on page 7-20.
  11608. Figure 7-5 shows how the AppleScript component uses information from its 'aeut' resource and an application’s 'aete' resource to execute a script that consists of AppleScript statements displayed in a script editor window. When a user executes the script from the script editor (for example, by pressing the Run button in the Script Editor application), the AppleScript component first compiles the script into the equivalent compiled expressions, using information from its 'aeut' resource and the application’s 'aete' resource to map application-specific terms in the script with the equivalent Apple events and Apple event parameters. The AppleScript component then evaluates each expression and performs actions or sends Apple events as appropriate. 
  11609. For example, the AppleScript component evaluates the expression
  11610. 2*3
  11611. as the value 6. The AppleScript component can then decompile and display this value in the script editor window, assign it to a variable, or otherwise manipulate it according to the rest of the script. However, to compile the statement
  11612. print Chart 1 of document "Sales Report"
  11613. the AppleScript component uses its 'aeut' resource and the SurfWriter application’s 'aete' resource to associate the terms used in the script with the Print Apple event, the object class for charts, and the object class for documents, so that it can describe the event accurately in the form of a compiled expression. When the AppleScript component evaluates the compiled expression, it creates and sends a Print event whose direct parameter is an object specifier record that the SurfWriter application can resolve as the specified chart. The SurfWriter application then handles the Apple event by printing the chart as requested.
  11614. Figure 7-5    Role of the 'aete' and 'aeut' resources when the AppleScript component compiles and executes a script
  11615.  
  11616. Note that although Figure 7-5 shows only one Apple event generated as a result of executing a script, the AppleScript component could also send a series of Apple events to several different applications, depending on the content of the script.
  11617. A recordable application generally needs to be able to send itself a subset of the Apple events that it can handle as a scriptable application. A recordable event is any Apple event that any recordable application sends to itself while recording is turned on for the local computer (with the exception of events that the application explicitly identifies as not for recording purposes). After a user turns on recording from the Script Editor application, the Apple Event Manager sends copies of all recordable events to Script Editor. A scripting component previously selected by the user handles each copied event for Script Editor by translating the event and recording the translation as part of a Script Editor script. When a scripting component executes a recorded script, it sends the corresponding Apple events to the applications in which they were recorded.
  11618. Every scripting component must be able to handle copies of recordable events sent to a recording process (such as Script Editor) by recording them in an appropriate form. For example, as shown in Figure 7-6, the AppleScript component records copies of recordable events in the form of compiled expressions. The AppleScript component can then use information from its 'aeut' resource and the application’s 'aete' resource to translate the compiled expressions into the appropriate human-language terms and display them as AppleScript statements in the script editor window. When the user opens a recorded script in Script Editor and presses Run, the AppleScript component recompiles the script if necessary and sends the Apple events described by the compiled expressions to the SurfWriter application, just as in Figure 7-5.
  11619. Figure 7-6    Role of the 'aete' and 'aeut' resources when the AppleScript component records and decompiles a script
  11620.  
  11621. If the user copies a chart from one document to another document and the SurfWriter application performs this task by sending itself Apple events, the equivalent statements in the recorded script might look something like this:
  11622. tell application "SurfWriter"
  11623.     select Chart 1 of document "Sales Chart"
  11624.     copy
  11625.     select paragraph 3 of document "Monthly Report"
  11626.     paste
  11627. end tell
  11628. To display these statements in the script editor window, the AppleScript component first translates the Set Data, Copy, and Paste Apple events sent by the recordable application into compiled expressions. It then uses information from its 'aeut' resource and the application’s 'aete' resource to decompile the compiled expressions and pass the equivalent source data to the script editor for display to the user. After completing a recording session, the user can edit and save the resulting script and execute it again at any time. 
  11629. As shown in Figure 7-5 and Figure 7-6, the AppleScript component uses information it obtains from the 'aeut' and 'aete' resources when it is compiling and decompiling scripts. Other scripting components might use the same information during execution or recording, or in other ways that are specific to each component.  
  11630. Dynamic Loading of Terminology Information
  11631.  
  11632. When a scripting component needs information about the user terminology defined in your application’s 'aete' resource, it sends a Get AETE event to your application. If your application does not handle the Get AETE event, the scripting component reads the terminology information it needs directly from your application’s 'aete' resource. 
  11633. Your application does not need to handle the Get AETE event unless it provides separate 'aete' resources for plug-in components. If your application does provide separate plug-in components, the Get AETE event allows it to gather terminology information from the 'aete' resources for the components that are currently running and add that information to the reply event. 
  11634. If your application handles the Get AETE event, you must also provide a scripting size resource. A scripting size resource is a resource of type 'scsz' that provides information about an application’s capabilities and preferences for use by scripting components.
  11635. To take advantage of dynamic loading, your application must be running. Note that if your application does not provide a handler for the Get AETE event, the scripting component can obtain terminology information directly from your application’s 'aete' resource even if your application is not running.  
  11636.  
  11637. Making Your Application Recordable
  11638.  
  11639. If you decide to make your application scriptable, you can also make it recordable. A recordable application is an application that uses Apple events to report user actions to the Apple Event Manager for recording purposes. A recordable event is any Apple event that a recordable application sends to itself while recording is turned on for the local computer (with the exception of events sent with the kAEDontRecord flag set in the sendMode parameter of AESend). 
  11640. When a user turns on recording by clicking the Record button in the Script Editor application, the Apple Event Manager sends copies of all subsequent recordable events to Script Editor. The AppleScript component handles each copied event for Script Editor by translating it into compiled expressions and recording the compiled expressions as part of a script. (Figure 7-6 on page 7-19 shows how the AppleScript component uses the 'aete' and 'aeut' resources when it records a script.) The user can view the equivalent decompiled source data in Script Editor while the script is being recorded. When a user executes a recorded script, the AppleScript component sends the corresponding Apple events to the applications in which they were recorded.
  11641. Applications generally have two parts: the code that implements the application’s user interface and the code that actually performs the work of the application when the user manipulates the interface. One way to make your application recordable is to separate these two parts of your application, using Apple events to connect user actions with the work your application performs. This is called factoring your application. In a fully factored application, almost all tasks are carried out in response to Apple events. The application translates low-level events that result in significant actions into recordable Apple events and then sends them to itself.
  11642. Factoring your application is the recommended method of making your application recordable. However, it is also possible for your application to report user actions by means of Apple events even though it actually performs those actions by some means other than Apple events. You can indicate that you want the Apple Event Manager to record events in this manner, without executing them, by adding the constant kAEDontExecute to the sendMode parameter of AESend.
  11643. Before you decide how to map the user’s potential actions to recordable Apple events supported by your application, you need to answer these questions:
  11644. n    What are the significant (that is, undoable) actions a user can perform with your application that you want to record? 
  11645. n    Which actions can you execute by means of Apple events, and which actions should cause Apple events to be sent but not executed?
  11646. n    How do you want to record actions that can be described in a scripting language in several different ways?
  11647. For example, if your application is a word processor, the user’s selection of a range of text should probably not generate an Apple event, because users often select various different pieces of text before deciding to do something to the selection. However, if a user changes the font of a selection, a recordable word processor should generate a corresponding Apple event so that the scripting component can record the change. 
  11648. In general, a recordable application should generate Apple events for any user action that the user could reverse by choosing Undo. A recordable application can usually handle a greater variety of Apple events than it can record, because it must record the same action the same way every time even though Apple events might be able to trigger that action in several different ways.
  11649. For more information about recordable applications, factoring, and the Apple Event Manager’s recording mechanism, see the chapter “Recording Apple Events” in this book. For a description of the role of the 'aete' and 'aeut' resources when the AppleScript component records a script, see “How AppleScript Uses Terminology Information,” which begins on page 7-17. 
  11650.  
  11651. Manipulating and Executing Scripts
  11652.  
  11653. Your application can use scripting component routines to manipulate and execute scripts written in any scripting language based on the OSA. This section describes how scripting components use script data and summarizes some of the tasks your application can perform by calling the standard scripting component routines.  
  11654. Your application can manipulate and execute scripts regardless of whether it is scriptable or recordable. However, if your application is scriptable, you can easily make it capable of manipulating and executing scripts that control its own behavior. For example, the forms application shown in Figure 7-4 on page 7-13 uses standard scripting component routines to execute a script whenever the cursor is in the appropriate field and the user presses Enter or Tab. Applications can also use scripting component routines to allow users to edit, recompile, save, and load such scripts in order to adapt them to their own purposes.
  11655. Before using any scripting component routines, your application must open a connection with at least one scripting component. After opening a connection with a component, your application receives a component instance that it can use as the first parameter for any scripting component routine. You can use the Component Manager to establish a connection with the generic scripting component or to establish an explicit connection with any other scripting component. Your application can open connections with different scripting components under different circumstances and, if necessary, simultaneously.
  11656. To manipulate or execute scripts written in any scripting language based on the OSA, your application can open a connection with the generic scripting component. The generic scripting component in turn attempts to open connections dynamically with the appropriate scripting component for a given script. If your application opens a connection with the generic scripting component, it can load and execute scripts created by any scripting component that is registered with the Component Manager on the current computer. The generic scripting component also provides routines that allow you to determine which scripting component created a particular script and to perform other useful tasks when you are using multiple scripting components.
  11657. To manipulate and execute scripts written in a single scripting language only, your application can open an explicit connection with the scripting component for that language. In this case your application can load and execute only those scripts that were created by that component; however, your application can also take advantage of additional routines and other special capabilities provided by the component.
  11658. After your application has established a connection with the appropriate scripting component for an existing script, it can use the standard scripting component routines to execute scripts. A script that has not yet been compiled consists of source data, or statements in a scripting language. Before executing source data, your application must use scripting component routines to compile it so that the scripting component can keep track of it in memory and execute it.  
  11659. Scripting components can refer to at least three kinds of script data in memory:
  11660. n    A compiled script consists of compiled code that an application can decompile into source data or execute using the standard scripting component routines. 
  11661. n    A script value consists of an integer, a string, a Boolean value, constants, PICT data, or any other fixed data returned or used by a scripting component in the course of executing a script.
  11662. n    A script context maintains context information for the execution of other scripts. A script context can also contain executable statements in a scripting language. Like a compiled script, a script context can be decompiled as source data.
  11663. For example, a script context can contain user-defined handlers for specific Apple events. In AppleScript, a script context that contains such handlers or other executable statements is called a script object. Handlers in a script object resemble HyperTalk message handlers. They consist of AppleScript statements and have no corresponding entry in Apple event dispatch tables.   
  11664. Scripting components keep track of script data in memory by means of script IDs of type OSAID. 
  11665. TYPE OSAID = LongInt;
  11666. A scripting component assigns a script ID to a compiled script or script context whenever the component creates or loads the corresponding script data. The scripting component routines that compile, load, and execute scripts all return script IDs, and you must pass valid script IDs to many of the other routines that manipulate scripts. 
  11667. Applications most commonly use scripting component routines to 
  11668. n    compile source data and execute the resulting compiled script, so that a user can create a new script and execute it immediately from within the application
  11669. n    get a handle to script data in a form that can be saved, and load and execute the script data again when necessary
  11670. n    allow users to modify a script, then recompile and save the script
  11671. n    redirect Apple events to script contexts
  11672. The remainder of this section provides an overview of the scripting component routines you can use to perform these tasks. 
  11673. Your application can also use scripting component routines to 
  11674. n    get information about scripts
  11675. n    get information about scripting components
  11676. n    coerce script values to descriptor records and vice versa
  11677. n    set a resume dispatch function and alternative send, create, and active functions for use by a scripting component
  11678. n    control the recording process directly, turning recording off and on and saving the recorded script for use by your application
  11679. The chapter “Scripting Components” in this book provides detailed information about using all the standard scripting component routines as well as additional routines provided by the AppleScript component and the generic scripting component.
  11680. Compiling, Saving, Modifying, and Executing Scripts
  11681.  
  11682. This section introduces some of the scripting component functions your application can use to compile, save, modify, and execute scripts.
  11683. To create and execute a script using the Script Editor application, a user can type the script, then press the Run button to execute it. Your application can provide similar capabilities by using these functions to compile source data and execute the resulting compiled script:
  11684. n    The OSACompile function takes a descriptor record with a handle to source data (usually text) and a script ID. If you specify kOSANullScript instead of an existing script ID, OSACompile returns a script ID for the new compiled script, which you can then pass to the OSAExecute function.
  11685. n    The OSAExecute function takes a script ID for a compiled script and a script ID for a script context, executes the script, and returns a script ID for the resulting script value.
  11686. The binding of any global variables in the compiled script is determined by the script context whose script ID you pass to OSAExecute. If you pass kOSANullScript instead of the script ID for a script context, the scripting component provides its own default context. If you want to provide your own script context rather than using the scripting component default context, you can use either OSACompile or OSAMakeContext to create a script context, which you can load and store just like a compiled script.
  11687. After creating a script and trying it out, a user may want to save it for future use. Your application should normally save its scripts as script data rather than source data, so that it can reload and execute the data without recompiling it. Before saving script data, you must first call the OSAStore function to get a handle to the data in the form of a descriptor record. You can then save the data to disk as a resource or write it to the data fork of a document. 
  11688. To allow a user to reload and execute a previously compiled and saved script, your application can call these functions:
  11689. n    The OSALoad function takes a descriptor record that contains a handle to the saved script data and returns a script ID for the compiled script.
  11690. n    The OSAExecute function takes a script ID for a compiled script and a script ID for a script context, executes the script, and returns a script ID for the resulting script value.
  11691. In most cases you will want to allow users to modify saved scripts and save them again. To allow a user to modify and save a compiled script, your application can call these functions:
  11692. n    The OSAGetSource function takes a script ID and returns a descriptor record with a handle to the equivalent source data.
  11693. n    The OSACompile function takes a descriptor record with a handle to source data and a script ID, and returns the same script ID updated so that it refers to the modified and recompiled script.
  11694. n    The OSAStore function takes a script ID and returns a copy of the corresponding script data in the form of a storage descriptor record.
  11695. You can pass the script ID for the compiled script to be modified to the OSAGetSource function, which returns a descriptor record with a handle to the equivalent source data. Your application can then present the source data to the user for editing. When the user has finished editing the source data, you can pass the modified source data and the original script ID to the OSACompile function to update the script ID so that it refers to the modified and recompiled script. Finally, to obtain a handle to the modified script data so you can save it in a resource or write it to the data fork of a document, you can pass the script ID for the modified compiled script to the OSAStore function. 
  11696. If your application has no further use for a compiled script or a resulting script value after successfully loading, saving, compiling, or executing a script, you can use the OSADispose function to release the memory assigned to them. The OSADispose function takes a script ID and releases the memory assigned to the corresponding script data. A script ID is no longer valid after the memory associated with it has been released. This means, for example, that a scripting component may assign a different script ID to the same compiled script each time you load it, and that a scripting component may reuse a script ID that is no longer associated with a specific script.
  11697. “Using Scripting Component Routines,” which begins on page 10-7, provides more information about the standard scripting component routines described in this section. 
  11698. Using a Script Context to Handle an Apple Event
  11699.  
  11700. One way to associate a script with an object is to associate a script context with a specific Apple event object—that is, with any object in your application that can be identified by an object specifier record. When an Apple event acts on an Apple event object with which a script context is associated, your application attempts to use the script context to handle the Apple event. This approach can be useful if you want to associate many different scripts with many different kinds of objects. 
  11701. Figure 7-7 illustrates one way that an application can use a script context to handle an Apple event. This example shows how you can use a general Apple event handler to provide initial processing for all Apple events received by your application. If an Apple event acts on an object with which a script context is associated, the general handler attempts to use the script context to handle the event.
  11702. The SurfWriter application in Figure 7-7 associates script contexts (called script objects in AppleScript) with geometric shapes such as circles or squares. These script contexts can contain one or more user-defined handlers for specific Apple events. For example, the script context shown in Figure 7-7 is associated with a circle and contains this handler:
  11703. on move to {x, y}
  11704.     continue move to {x, item 2 of position of this}
  11705. end move
  11706. This handler exists only as AppleScript statements in the script context and doesn’t have an entry in SurfWriter’s Apple event dispatch table. SurfWriter does have its own standard Apple event handlers installed in its Apple event dispatch table. When SurfWriter receives a Move event that acts on the circle with which this script context is associated, SurfWriter uses the handler in the script context to modify its own standard handling of the event. The rest of this section describes how this works.
  11707. Figure 7-7    Using a handler in a script context to handle an Apple event
  11708.  
  11709. The MyGeneralAppleEventHandler function in Figure 7-7 is installed in SurfWriter’s special handler dispatch table. Thus, MyGeneralAppleEventHandler provides initial processing for all Apple events received by SurfWriter. When it receives an Apple event, MyGeneralAppleEventHandler checks whether a script context is associated with the object on which the event acts. If so, MyGeneralAppleEventHandler passes the event and a script ID for the script context to the OSADoEvent function. If not, MyGeneralAppleEventHandler returns errAEEventNotHandled, which causes the Apple Event Manager to look for the appropriate handler in SurfWriter’s Apple event dispatch table.
  11710. The OSADoEvent function looks for a handler in the specified script context that can handle the specified event. If the script context doesn’t include an appropriate handler, OSADoEvent returns errAEEventNotHandled. If the script context includes an appropriate handler (in this example, a handler that begins on move), OSADoEvent attempts to use the handler to handle the event.
  11711. When it encounters the continue statement during execution of the on move handler shown in Figure 7-7, the AppleScript component calls SurfWriter’s resume dispatch function. A resume dispatch function takes an Apple event and invokes the ap